<commit_before>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using Packager.Exceptions;
using Packager.Extensions;
using Packager.Models;
using Packager.Models.BextModels;
using Packager.Models.FileModels;
using Packager.Models.ResultModels;
using Packager.Observers;
using Packager.Providers;
using Packager.Test.Mocks;
using Packager.Utilities;
using Packager.Validators.Attributes;

namespace Packager.Test.Utilities
{
    [TestFixture]
    public class FFMPEGRunnerTests
    {
        [SetUp]
        public virtual void BeforeEach()
        {
            ProgramSettings = Substitute.For<IProgramSettings>();
            ProgramSettings.FFMPEGPath.Returns(FFMPEGPath);
            ProgramSettings.ProcessingDirectory.Returns(BaseProcessingDirectory);
            ProgramSettings.FFMPEGAudioAccessArguments.Returns(AudioAccessArguments);
            ProgramSettings.FFMPEGAudioProductionArguments.Returns(AudioProductionArguments);

            ProcessRunnerResult = Substitute.For<IProcessResult>();
            ProcessRunnerResult.ExitCode.Returns(0);
            ProcessRunnerResult.StandardError.Returns(StandardErrorOutput);

            MasterFileModel = new ObjectFileModel(MasterFileName);

            ProcessRunner = Substitute.For<IProcessRunner>();

            Observers = Substitute.For<IObserverCollection>();
            FileProvider = Substitute.For<IFileProvider>();

            Hasher = Substitute.For<IHasher>();
            Hasher.Hash(Arg.Any<string>()).Returns(x => Task.FromResult($"{Path.GetFileName(x.Arg<string>())} hash value"));

            Metadata = MockBextMetadata.Get();

            Runner = new FFMPEGRunner(ProgramSettings, ProcessRunner, Observers, FileProvider, Hasher);

            DoCustomSetup();
        }


        private const string FFMPEGPath = "ffmpeg.exe";
        private const string AudioProductionArguments = "production arguments";
        private const string AudioAccessArguments = "production arguments";
        private const string BaseProcessingDirectory = "base";
        private const string MasterFileName = "MDPI_123456789_01_pres.wav";

        private const string StandardErrorOutput = "Standard error output";
        private ObjectFileModel MasterFileModel { get; set; }

        private IProcessRunner ProcessRunner { get; set; }
        private IObserverCollection Observers { get; set; }
        private IFileProvider FileProvider { get; set; }
        private FFMPEGRunner Runner { get; set; }
        private ObjectFileModel Result { get; set; }
        private IProcessResult ProcessRunnerResult { get; set; }
        private IProgramSettings ProgramSettings { get; set; }

        private BextMetadata Metadata { get; set; }

        private IHasher Hasher { get; set; }


        protected virtual void DoCustomSetup()
        {
        }

        public class WhenNormalizingOriginals : FFMPEGRunnerTests
        {
            public override async void BeforeEach()
            {
                base.BeforeEach();

                ProductionFileModel = new ObjectFileModel(ProductionFileName);

                Originals = new List<ObjectFileModel>
                {
                    ProductionFileModel,
                    PreservationFileModel
                };

                // configure file provider to assert original should exist
                FileProvider.FileExists(Path.Combine(BaseProcessingDirectory, ProductionFileModel.GetOriginalFolderName(), ProductionFileName)).Returns(true);
                FileProvider.FileExists(Path.Combine(BaseProcessingDirectory, PreservationFileModel.GetOriginalFolderName(), MasterFileName)).Returns(true);

                // configure file provider to assert normalized versions do not exist
                FileProvider.FileDoesNotExist(Path.Combine(BaseProcessingDirectory, ProductionFileModel.GetFolderName(), ProductionFileName)).Returns(true);
                FileProvider.FileDoesNotExist(Path.Combine(BaseProcessingDirectory, PreservationFileModel.GetFolderName(), MasterFileName)).Returns(true);
            }

            private List<ObjectFileModel> Originals { get; set; }

            private const string ProductionFileName = "MDPI_123456789_01_prod.wav";

            private ObjectFileModel ProductionFileModel { get; set; }
            private ObjectFileModel PreservationFileModel => MasterFileModel;

            public class WhenThingsGoWell : WhenNormalizingOriginals
            {
                public override async void BeforeEach()
                {
                    base.BeforeEach();

                    ProcessRunner.Run(Arg.Any<ProcessStartInfo>()).ReturnsForAnyArgs(x =>
                    {
                        ProcessRunnerResult.StartInfo.Returns(x.Arg<ProcessStartInfo>());
                        return Task.FromResult(ProcessRunnerResult);
                    });

                    await Runner.Normalize(PreservationFileModel, Metadata);
                }

                private ProcessStartInfo StartInfo { get; set; }

                protected override void DoCustomSetup()
                {
                    base.DoCustomSetup();<commit_msg>adding tests<commit_after>﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using Packager.Exceptions;
using Packager.Extensions;
using Packager.Models;
using Packager.Models.BextModels;
using Packager.Models.FileModels;
using Packager.Models.ResultModels;
using Packager.Observers;
using Packager.Providers;
using Packager.Test.Mocks;
using Packager.Utilities;
using Packager.Validators.Attributes;

namespace Packager.Test.Utilities
{
    [TestFixture]
    public class FFMPEGRunnerTests
    {
        [SetUp]
        public virtual void BeforeEach()
        {
            ProgramSettings = Substitute.For<IProgramSettings>();
            ProgramSettings.FFMPEGPath.Returns(FFMPEGPath);
            ProgramSettings.ProcessingDirectory.Returns(BaseProcessingDirectory);
            ProgramSettings.FFMPEGAudioAccessArguments.Returns(AudioAccessArguments);
            ProgramSettings.FFMPEGAudioProductionArguments.Returns(AudioProductionArguments);

            ProcessRunnerResult = Substitute.For<IProcessResult>();
            ProcessRunnerResult.ExitCode.Returns(0);
            ProcessRunnerResult.StandardError.Returns(StandardErrorOutput);

            MasterFileModel = new ObjectFileModel(MasterFileName);

            ProcessRunner = Substitute.For<IProcessRunner>();

            Observers = Substitute.For<IObserverCollection>();
            FileProvider = Substitute.For<IFileProvider>();

            Hasher = Substitute.For<IHasher>();
            Hasher.Hash(Arg.Any<string>()).Returns(x => Task.FromResult($"{Path.GetFileName(x.Arg<string>())} hash value"));

            Metadata = MockBextMetadata.Get();

            Runner = new FFMPEGRunner(ProgramSettings, ProcessRunner, Observers, FileProvider, Hasher);

            DoCustomSetup();
        }


        private const string FFMPEGPath = "ffmpeg.exe";
        private const string AudioProductionArguments = "production arguments";
        private const string AudioAccessArguments = "production arguments";
        private const string BaseProcessingDirectory = "base";
        private const string MasterFileName = "MDPI_123456789_01_pres.wav";

        private const string StandardErrorOutput = "Standard error output";
        private ObjectFileModel MasterFileModel { get; set; }

        private IProcessRunner ProcessRunner { get; set; }
        private IObserverCollection Observers { get; set; }
        private IFileProvider FileProvider { get; set; }
        private FFMPEGRunner Runner { get; set; }
        private ObjectFileModel Result { get; set; }
        private IProcessResult ProcessRunnerResult { get; set; }
        private IProgramSettings ProgramSettings { get; set; }

        private BextMetadata Metadata { get; set; }

        private IHasher Hasher { get; set; }


        protected virtual void DoCustomSetup()
        {
        }

        public class WhenInitializing : FFMPEGRunnerTests
        {
            public class WhenProductionWriteBextArgsNotPresent : WhenInitializing
            {
            
                [Test]
                public void ItShouldSetArgsCorrectly()
                {
                    Assert.That(Regex.Matches(Runner.ProductionArguments, " -write_bext 1").Count, Is.EqualTo(1));
                }
            }

            public class WhenProductionRiffArgsNotPresent : WhenInitializing
            {
                [Test]
                public void ItShouldSetArgsCorrectly()
                {
                    Assert.That(Regex.Matches(Runner.ProductionArguments, " -rf64 auto").Count, Is.EqualTo(1));
                }
            }

            public class WhenProductionWriteBextArgsPresent : WhenInitializing
            {
                public override void BeforeEach()
                {
                    base.BeforeEach();
                    ProgramSettings.FFMPEGAudioProductionArguments.Returns(" -write_bext 1");
                    Runner = new FFMPEGRunner(ProgramSettings, ProcessRunner, Observers, FileProvider, Hasher);
                }

                [Test]
                public void ItShouldSetArgsCorrectly()
                {
                    Assert.That(Regex.Matches(Runner.ProductionArguments, " -write_bext 1").Count, Is.EqualTo(1));
                }
            }

            public class WhenProductionRiffArgsPresent : WhenInitializing
            {
                public override void BeforeEach()
                {
                    base.BeforeEach();
                    ProgramSettings.FFMPEGAudioProductionArguments.Returns(" -rf64 auto");
                    Runner = new FFMPEGRunner(ProgramSettings, ProcessRunner, Observers, FileProvider, Hasher);
                }

                [Test]
                public void ItShouldSetArgsCorrectly()
                {
                    Assert.That(Regex.Matches(Runner.ProductionArguments, " -rf64 auto").Count, Is.EqualTo(1));
                }
            }

            public class WhenPassedInProductionArgumentsNull : WhenInitializing
            {
                public override void BeforeEach()
                {
                    base.BeforeEach();
                    ProgramSettings.FFMPEGAudioProductionArguments.Returns((string)null);
                    Runner = new FFMPEGRunner(ProgramSettings, ProcessRunner, Observers, FileProvider, Hasher);
                }

                [Test]
                public void ItShouldNotModifyArguments()
                {
                    Assert.That(Runner.ProductionArguments, Is.Null);
                }
            }

            public class WhenPassedInProductionArgumentsEmpty : WhenInitializing
            {
                public override void BeforeEach()
                {
                    base.BeforeEach();
                    ProgramSettings.FFMPEGAudioProductionArguments.Returns("");
                    Runner = new FFMPEGRunner(ProgramSettings, ProcessRunner, Observers, FileProvider, Hasher);
                }

                [Test]
                public void ItShouldNotModifyArguments()
                {
                    Assert.That(Runner.ProductionArguments, Is.EqualTo(""));
                }
            }
        }

        public class WhenNormalizingOriginals : FFMPEGRunnerTests
        {
            public override async void BeforeEach()
            {
                base.BeforeEach();

                ProductionFileModel = new ObjectFileModel(ProductionFileName);

                Originals = new List<ObjectFileModel>
                {
                    ProductionFileModel,
                    PreservationFileModel
                };

                // configure file provider to assert original should exist
                FileProvider.FileExists(Path.Combine(BaseProcessingDirectory, ProductionFileModel.GetOriginalFolderName(), ProductionFileName)).Returns(true);
                FileProvider.FileExists(Path.Combine(BaseProcessingDirectory, PreservationFileModel.GetOriginalFolderName(), MasterFileName)).Returns(true);

                // configure file provider to assert normalized versions do not exist
                FileProvider.FileDoesNotExist(Path.Combine(BaseProcessingDirectory, ProductionFileModel.GetFolderName(), ProductionFileName)).Returns(true);
                FileProvider.FileDoesNotExist(Path.Combine(BaseProcessingDirectory, PreservationFileModel.GetFolderName(), MasterFileName)).Returns(true);
            }

            private List<ObjectFileModel> Originals { get; set; }

            private const string ProductionFileName = "MDPI_123456789_01_prod.wav";

            private ObjectFileModel ProductionFileModel { get; set; }
            private ObjectFileModel PreservationFileModel => MasterFileModel;

            
            public class WhenThingsGoWell : WhenNormalizingOriginals
            {
                public override async void BeforeEach()
                {
                    base.BeforeEach();

                    ProcessRunner.Run(Arg.Any<ProcessStartInfo>()).ReturnsForAnyArgs(x =>
                    {
                        ProcessRunnerResult.StartInfo.Returns(x.Arg<ProcessStartInfo>());
                        return Task.FromResult(ProcessRunnerResult);
                    });

                    await Runner.Normalize(PreservationFileModel, Metadata);
                }

                private ProcessStartInfo StartInfo { get; set; }

                protected override void DoCustomSetup()
                {
                    base.DoCustomSetup();
{'fraction_non_alphanumeric': 0.07596023174307989, 'fraction_numerical': 0.00422001287461555, 'mean_word_length': 2.2172112287160606, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6191826', 'n_tokens_mistral': 3379, 'n_tokens_neox': 3176, 'n_words': 664}