/// <summary>
 /// Initializes a new instance of the <see cref="ActivePhysicalMachineEnvironment"/> class.
 /// </summary>
 /// <param name="id">The ID of the environment.</param>
 /// <param name="terminateEnvironment">The action used to terminate the environment.</param>
 /// <param name="commands">The object that provides the commands used to communicate with the environment.</param>
 /// <param name="notifications">The object that provides notifications from the environment.</param>
 /// <param name="uploads">The object that tracks the files available for upload.</param>
 /// <exception cref="ArgumentNullException">
 ///     Thrown if <paramref name="id"/> is <see langword="null" />.
 /// </exception>
 /// <exception cref="ArgumentNullException">
 ///     Thrown if <paramref name="terminateEnvironment"/> is <see langword="null" />.
 /// </exception>
 /// <exception cref="ArgumentNullException">
 ///     Thrown if <paramref name="commands"/> is <see langword="null" />.
 /// </exception>
 /// <exception cref="ArgumentNullException">
 ///     Thrown if <paramref name="notifications"/> is <see langword="null" />.
 /// </exception>
 /// <exception cref="ArgumentNullException">
 ///     Thrown if <paramref name="uploads"/> is <see langword="null" />.
 /// </exception>
 public ActivePhysicalMachineEnvironment(
     string id,
     Action terminateEnvironment,
     IExecuteTestStepsCommands commands,
     ITestExecutionNotifications notifications,
     IStoreUploads uploads)
     : base(id, terminateEnvironment, commands, notifications, uploads)
 {
 }
 /// <summary>
 /// Constructs a new active environment proxy.
 /// </summary>
 /// <param name="environment">The specification for the environment.</param>
 /// <param name="preTerminateEnvironment">The action executed just prior to terminating the environment.</param>
 /// <param name="postTerminateEnvironment">The action executed after terminating the environment.</param>
 /// <param name="commands">The object that provides the commands used to communicate with the environment.</param>
 /// <param name="notifications">The object that provides notifications from the environment.</param>
 /// <param name="uploads">The object that tracks the files available for upload.</param>
 /// <param name="sectionBuilder">
 /// The object used to write information to the report about the starting and stopping of the environment.
 /// </param>
 /// <returns>A new active environment proxy object.</returns>
 protected abstract IActiveEnvironment ConstructEnvironmentProxy(
     MachineDescription environment,
     Action preTerminateEnvironment,
     Action postTerminateEnvironment,
     IExecuteTestStepsCommands commands,
     ITestExecutionNotifications notifications,
     IStoreUploads uploads,
     ITestSectionBuilder sectionBuilder);
        /// <summary>
        /// Initializes a new instance of the <see cref="ActiveMachineEnvironment"/> class.
        /// </summary>
        /// <param name="id">The ID of the environment.</param>
        /// <param name="terminateEnvironment">The action used to terminate the environment.</param>
        /// <param name="commands">The object that provides the commands used to communicate with the environment.</param>
        /// <param name="notifications">The object that provides notifications from the environment.</param>
        /// <param name="uploads">The object that tracks the files available for upload.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="id"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="terminateEnvironment"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="commands"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="notifications"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="uploads"/> is <see langword="null" />.
        /// </exception>
        protected ActiveMachineEnvironment(
            string id,
            Action terminateEnvironment,
            IExecuteTestStepsCommands commands,
            ITestExecutionNotifications notifications,
            IStoreUploads uploads)
        {
            {
                Lokad.Enforce.Argument(() => id);
                Lokad.Enforce.Argument(() => terminateEnvironment);
                Lokad.Enforce.Argument(() => commands);
                Lokad.Enforce.Argument(() => notifications);
                Lokad.Enforce.Argument(() => uploads);
            }

            m_Id = id;
            m_TerminateEnvironment = terminateEnvironment;
            m_Commands = commands;
            m_Uploads = uploads;

            m_Notifications = notifications;
            m_Notifications.OnExecutionProgress += HandleOnExecutionProgress;
            m_Notifications.OnTestCompletion += HandleOnTestCompletion;
        }
        /// <summary>
        /// Constructs a new active environment proxy.
        /// </summary>
        /// <param name="environment">The specification for the environment.</param>
        /// <param name="preTerminateEnvironment">The action executed just prior to terminating the environment.</param>
        /// <param name="postTerminateEnvironment">The action executed after terminating the environment.</param>
        /// <param name="commands">The object that provides the commands used to communicate with the environment.</param>
        /// <param name="notifications">The object that provides notifications from the environment.</param>
        /// <param name="uploads">The object that tracks the files available for upload.</param>
        /// <param name="sectionBuilder">
        /// The object used to write information to the report about the starting and stopping of the environment.
        /// </param>
        /// <returns>A new active environment proxy object.</returns>
        protected override IActiveEnvironment ConstructEnvironmentProxy(
            MachineDescription environment,
            Action preTerminateEnvironment,
            Action postTerminateEnvironment,
            IExecuteTestStepsCommands commands,
            ITestExecutionNotifications notifications,
            IStoreUploads uploads,
            ITestSectionBuilder sectionBuilder)
        {
            Action shutDownAction =
                () =>
                {
                    preTerminateEnvironment();
                    ShutdownVirtualMachine(environment, sectionBuilder);
                    postTerminateEnvironment();
                };

            return new ActiveHypervEnvironment(
                environment.Id,
                shutDownAction,
                commands,
                notifications,
                uploads);
        }
        /// <summary>
        /// Constructs a new active environment proxy.
        /// </summary>
        /// <param name="environment">The specification for the environment.</param>
        /// <param name="preTerminateEnvironment">The action executed just prior to terminating the environment.</param>
        /// <param name="postTerminateEnvironment">The action executed after terminating the environment.</param>
        /// <param name="commands">The object that provides the commands used to communicate with the environment.</param>
        /// <param name="notifications">The object that provides notifications from the environment.</param>
        /// <param name="uploads">The object that tracks the files available for upload.</param>
        /// <param name="sectionBuilder">
        /// The object used to write information to the report about the starting and stopping of the environment.
        /// </param>
        /// <returns>A new active environment proxy object.</returns>
        protected override IActiveEnvironment ConstructEnvironmentProxy(
            MachineDescription environment,
            Action preTerminateEnvironment,
            Action postTerminateEnvironment,
            IExecuteTestStepsCommands commands,
            ITestExecutionNotifications notifications,
            IStoreUploads uploads,
            ITestSectionBuilder sectionBuilder)
        {
            Action shutDownAction =
                () =>
                {
                    preTerminateEnvironment();
                    postTerminateEnvironment();

                    sectionBuilder.AddInformationMessage(
                        string.Format(
                            CultureInfo.InvariantCulture,
                            "Terminated machine: {0}",
                            environment.NetworkName));
                    sectionBuilder.FinalizeAndStore(true);
                };

            return new ActivePhysicalMachineEnvironment(
                environment.Id,
                shutDownAction,
                commands,
                notifications,
                uploads);
        }