private static UploadReportFilesForTestStep BuildReportFileUploader(IComponentContext context, string storageDirectory, EndpointId hostId)
        {
            UploadReportFilesForTestStep uploader =
                (stepIndex, filesToUpload) =>
                {
                    if (filesToUpload.Count == 0)
                    {
                        return;
                    }

                    var path = Path.Combine(
                        storageDirectory,
                        string.Format(
                            CultureInfo.InvariantCulture,
                            "TestStepReport-{0}.zip",
                            stepIndex));
                    var package = new TestStepPackage(stepIndex);
                    foreach (var pair in filesToUpload)
                    {
                        var filePath = pair.Key.FullName;
                        var baseDirectory = pair.Value.FullName;

                        var relativePath = filePath.Substring(baseDirectory.Length).TrimStart(Path.DirectorySeparatorChar);
                        package.Add(filePath, relativePath);
                    }

                    package.PackTo(path);

                    var uploads = context.Resolve<IStoreUploads>();
                    var token = uploads.Register(path);

                    var hub = context.Resolve<ISendCommandsToRemoteEndpoints>();
                    if (!hub.HasCommandFor(hostId, typeof(ITransferTestReportDataCommands)))
                    {
                        throw new MissingCommandSetException();
                    }

                    var command = hub.CommandsFor<ITransferTestReportDataCommands>(hostId);

                    var id = EndpointIdExtensions.CreateEndpointIdForCurrentProcess();
                    Action toExecute =
                        () =>
                        {
                            var task = command.PrepareReportFilesForTransfer(
                                stepIndex,
                                id,
                                token);
                            task.Wait();
                        };
                    CommandSetGuard.GuardAgainstCommunicationFailure(toExecute);
                };

            return uploader;
        }
        private static void RegisterTestFilePacker(ContainerBuilder builder)
        {
            builder.Register(c => new TestSuitePackage())
                .As<ITestSuitePackage>()
                .SingleInstance();

            builder.Register(
                c =>
                {
                    var ctx = c.Resolve<IComponentContext>();
                    StoreFileDataForEnvironment func =
                        (environment, stepOrder, storedPath, filePath) =>
                        {
                            var suitePackage = ctx.Resolve<ITestSuitePackage>();
                            var environmentPackage = suitePackage.Environment(environment);
                            if (environmentPackage == null)
                            {
                                environmentPackage = new TestEnvironmentPackage(environment);
                                suitePackage.Add(environmentPackage);
                            }

                            var testPackage = environmentPackage.Test(stepOrder);
                            if (testPackage == null)
                            {
                                testPackage = new TestStepPackage(stepOrder);
                                environmentPackage.Add(testPackage);
                            }

                            testPackage.Add(filePath, storedPath);
                        };

                    return func;
                });
        }
        /// <summary>
        /// Unpacks the test files from a given package file to a given destination location.
        /// </summary>
        /// <param name="destinationDirectory">The full path to the destination directory.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="destinationDirectory"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///     Thrown if <paramref name="destinationDirectory"/> is an empty string.
        /// </exception>
        /// <exception cref="NeedPackagePathException">
        ///     Thrown if no <see cref="PackagePath"/> has been provided.
        /// </exception>
        public void UnpackTo(string destinationDirectory)
        {
            {
                Lokad.Enforce.Argument(() => destinationDirectory);
                Lokad.Enforce.Argument(() => destinationDirectory, Lokad.Rules.StringIs.NotEmpty);
                Lokad.Enforce.With<NeedPackagePathException>(
                    !string.IsNullOrWhiteSpace(PackagePath),
                    Resources.Exceptions_Messages_NeedPackagePath);
            }

            if (!Directory.Exists(destinationDirectory))
            {
                Directory.CreateDirectory(destinationDirectory);
            }

            using (var zipFile = ZipFile.Read(PackagePath))
            {
                foreach (var entry in zipFile)
                {
                    if (string.Equals(MetaDataFileName, entry.FileName))
                    {
                        ExtractEnvironmentName(entry);
                        continue;
                    }

                    entry.Extract(destinationDirectory, ExtractExistingFileAction.OverwriteSilently);

                    var step = new TestStepPackage();
                    step.LoadFrom(Path.Combine(destinationDirectory, entry.FileName));
                    m_TestSteps.Add(step.TestStepIndex, step);
                }
            }
        }
        /// <summary>
        /// Prepares the report files for upload.
        /// </summary>
        /// <param name="testId">The ID of the test to which the files belong.</param>
        /// <param name="testStepIndex">The index of the test step for which the report files are being uploaded.</param>
        /// <param name="callingEndpoint">The ID of the endpoint that called the method.</param>
        /// <param name="token">The upload token used to register the report files that need to be uploaded.</param>
        /// <returns>An upload token that can be used to download the desired files.</returns>
        public Task PrepareReportFilesForTransfer(int testId, int testStepIndex, EndpointId callingEndpoint, UploadToken token)
        {
            m_Diagnostics.Log(
                LevelToLog.Trace,
                MasterServiceConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.Log_Messages_TransferingTestStepReportFiles_WithTestAndTestStep,
                    testId,
                    testStepIndex));

            var downloadDirectory = TestHelpers.StoragePathForReportFiles(testId, m_Configuration, m_FileSystem);
            if (!m_FileSystem.Directory.Exists(downloadDirectory))
            {
                 m_FileSystem.Directory.CreateDirectory(downloadDirectory);
            }

            var fileName = string.Format(
                CultureInfo.InvariantCulture,
                "{0}_{1}.reportfiles",
                testId,
                testStepIndex);
            var filePath = m_FileSystem.Path.Combine(
                downloadDirectory,
                string.Format(
                    CultureInfo.InvariantCulture,
                    "{0}.zip",
                    fileName));
            var fileStream = m_DataDownload(
                callingEndpoint,
                token,
                filePath);
            var uploadTask = fileStream.ContinueWith(
                file =>
                {
                    try
                    {
                        var testPackage = new TestStepPackage(testStepIndex);

                        var unpackDirectory = Path.Combine(downloadDirectory, fileName);
                        testPackage.LoadAndUnpack(file.Result.FullName, unpackDirectory);

                        var notifications = m_ActiveTests.NotificationsFor(testId);
                        foreach (var notification in notifications)
                        {
                            foreach (var storedFile in testPackage.StoredFiles())
                            {
                                var relativePath = storedFile.FullName.Substring(downloadDirectory.Length).TrimStart(Path.DirectorySeparatorChar);
                                notification.StoreReportFile(storedFile.FullName, relativePath);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        m_Diagnostics.Log(
                            LevelToLog.Error,
                            MasterServiceConstants.LogPrefix,
                            string.Format(
                                CultureInfo.InvariantCulture,
                                Resources.Log_Messages_TransferingTestStepReportFilesFailed_WithTestAndTestStepAndError,
                                testId,
                                testStepIndex,
                                e));
                    }
                });

            return uploadTask;
        }