public void GenerateCalcs_InvalidSourceCodeNormaliseWhitespaceFails_ReturnsError()
        {
            CompilerOptions          compilerOptions          = new CompilerOptions();
            CalculationTypeGenerator calculationTypeGenerator = new CalculationTypeGenerator(compilerOptions, _fundingLineRoundingSettings.Object);

            string badCode = @"Dim Filter as Decimal
Dim APTPhase as String
Dim CensusPhase as String
Dim Result as Decimal

Filter = FILTERSBSAcademiesFilter()
APTPhase = Datasets.APTInputsAndAdjustments.Phase()
CensusPhase = Datasets.CensusPupilCharacteristics.Phase()

If Filter = 0 then

Return Exclude()

Else

If string.isnullorempty(APTPhase) then Result = 0

Else If CensusPhase = ""PRIMARY"" then Result = 1

Else If CensusPhase = ""MIDDLE-DEEMED PRIMARY"" then Result = 2

Else If CensusPhase = ""SECONDARY"" then Result = 3

Else If CensusPhase = ""MIDDLE-DEEMED SECONDARY"" then Result = 4

End If
End If
End If

Return Result + 0";

            IEnumerable <Calculation> calculations = new[] { new Calculation {
                                                                 Current = new CalculationVersion {
                                                                     SourceCode = badCode, SourceCodeName = "Broken"
                                                                 }
                                                             } };

            Dictionary <string, Funding> fundingLines = new Dictionary <string, Funding>();

            Action generate = () => calculationTypeGenerator.GenerateCalcs(calculations, fundingLines).ToList();

            generate
            .Should()
            .Throw <Exception>()
            .And.Message
            .Should()
            .StartWith("Error compiling source code. Please check your code's structure is valid. ");
        }
        public void GenerateCalcs_GivenCalculationsAndCompilerOptionsUseLegacyCodeIsSet_TheEnsuresCorrectInheritanceStatement(bool useLegacyCode, string expectedInheritsStatement)
        {
            // Arrange
            CompilerOptions compilerOptions = new CompilerOptions
            {
                UseLegacyCode = useLegacyCode,
            };

            CalculationTypeGenerator calculationTypeGenerator = new CalculationTypeGenerator(compilerOptions);

            // Act
            IEnumerable <SourceFile> results = calculationTypeGenerator.GenerateCalcs(new List <Calculation>());

            // Assert
            results.Should().HaveCount(1);

            results.First().SourceCode.Should().Contain(expectedInheritsStatement);
        }
        public void GenerateCalcs_GivenCalculationsAndCompilerOptionsOff_ThenOptionsGenerated()
        {
            // Arrange
            List <Calculation> calculations = new List <Calculation>();

            CompilerOptions compilerOptions = new CompilerOptions
            {
                OptionStrictEnabled = false
            };

            CalculationTypeGenerator calculationTypeGenerator = new CalculationTypeGenerator(compilerOptions);

            // Act
            IEnumerable <SourceFile> results = calculationTypeGenerator.GenerateCalcs(calculations);

            // Assert
            results.Should().HaveCount(1);
            results.First().SourceCode.Should().StartWith("Option Strict Off");
        }
        public void GenerateCalcs_GivenCalculationsAndCompilerOptionsStrictOn_ThenOptionStrictGenerated()
        {
            // Arrange
            List <Calculation>           calculations = new List <Calculation>();
            Dictionary <string, Funding> fundingLines = new Dictionary <string, Funding>();

            CompilerOptions compilerOptions = new CompilerOptions
            {
                OptionStrictEnabled = true
            };

            CalculationTypeGenerator calculationTypeGenerator = new CalculationTypeGenerator(compilerOptions, _fundingLineRoundingSettings.Object);

            // Act
            IEnumerable <SourceFile> results = calculationTypeGenerator.GenerateCalcs(calculations, fundingLines);

            // Assert
            results.Should().HaveCount(1);
            results.First().SourceCode.Should().StartWith("Option Strict On");
        }
        public void GenerateCalcs_MissingSourceCodeName_ReturnsError()
        {
            string id = "42";

            CompilerOptions          compilerOptions          = new CompilerOptions();
            CalculationTypeGenerator calculationTypeGenerator = new CalculationTypeGenerator(compilerOptions);

            IEnumerable <Calculation> calculations = new[] { new Calculation {
                                                                 Current = new CalculationVersion {
                                                                     SourceCode = "Return 1"
                                                                 }, Id = id
                                                             } };

            Action generate = () => calculationTypeGenerator.GenerateCalcs(calculations).ToList();

            generate
            .Should()
            .Throw <Exception>()
            .And.Message
            .Should()
            .Be($"Calculation source code name is not populated for calc {id}");
        }
        public void GenerateCalcs_ThenEntryFunctionGenerated()
        {
            // Arrange
            Dictionary <string, Funding> fundingLines = new Dictionary <string, Funding>();

            CompilerOptions compilerOptions = new CompilerOptions
            {
                OptionStrictEnabled = false
            };

            CalculationTypeGenerator calculationTypeGenerator = new CalculationTypeGenerator(compilerOptions, _fundingLineRoundingSettings.Object);

            // Act
            IEnumerable <SourceFile> results = calculationTypeGenerator.GenerateCalcs(new List <Calculation>(), fundingLines);

            // Assert
            results.Should().HaveCount(1);
            // Assert
            results.Should().HaveCount(1);
            results.First()
            .SourceCode
            .Should().
            Contain("Public MainCalc As Func(Of Boolean, (CalculationResults As Dictionary(Of String, String()), FundingLineResults As Dictionary(Of String, String()))) = Function(allCalculations)");
        }
        public void GenerateCalcs_MissingSourceCodeName_ReturnsError()
        {
            string id = "42";

            CompilerOptions          compilerOptions          = new CompilerOptions();
            CalculationTypeGenerator calculationTypeGenerator = new CalculationTypeGenerator(compilerOptions, _fundingLineRoundingSettings.Object);

            IEnumerable <Calculation> calculations = new[] { new Calculation {
                                                                 Current = new CalculationVersion {
                                                                     SourceCode = "Return 1", Namespace = CalculationNamespace.Additional
                                                                 }, Id = id
                                                             } };

            Dictionary <string, Funding> fundingLines = new Dictionary <string, Funding>();

            Action generate = () => calculationTypeGenerator.GenerateCalcs(calculations, fundingLines).ToList();

            generate
            .Should()
            .Throw <Exception>()
            .And.Message
            .Should()
            .Be($"Calculation source code name is not populated for calc {id}");
        }