context: // Copyright (c) .NET Foundation. All rights reserved.
  // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  
  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  using System.Reflection;
  using System.Text;
  using Microsoft.AspNet.Mvc.Razor.Directives;
  using Microsoft.AspNet.Mvc.Razor.Internal;
  using Microsoft.AspNet.Razor;
  using Microsoft.AspNet.Razor.Chunks;
  using Microsoft.AspNet.Razor.Chunks.Generators;
  using Microsoft.AspNet.Razor.CodeGenerators;
  using Microsoft.AspNet.Razor.CodeGenerators.Visitors;
  using Microsoft.AspNet.Razor.Parser;
  using Microsoft.Framework.Internal;
  using Xunit;
  
  namespace Microsoft.AspNet.Mvc.Razor
  {
      public class MvcRazorHostTest
      {
          private static Assembly _assembly = typeof(MvcRazorHostTest).Assembly;
  
          [Theory]
          [InlineData("//")]
          [InlineData("C:/")]
          [InlineData(@"\\")]
          [InlineData(@"C:\")]
          public void DecorateRazorParser_DesignTimeRazorPathNormalizer_NormalizesChunkInheritanceUtilityPaths(
              string rootPrefix)
          {
              // Arrange
              var rootedAppPath = $"{rootPrefix}SomeComputer/Location/Project/";
              var rootedFilePath = $"{rootPrefix}SomeComputer/Location/Project/src/file.cshtml";
              var host = new MvcRazorHost(
                  chunkTreeCache: null,
                  pathNormalizer: new DesignTimeRazorPathNormalizer(rootedAppPath));
              var parser = new RazorParser(
                  host.CodeLanguage.CreateCodeParser(),
                  host.CreateMarkupParser(),
                  tagHelperDescriptorResolver: null);
              var chunkInheritanceUtility = new PathValidatingChunkInheritanceUtility(host);
              host.ChunkInheritanceUtility = chunkInheritanceUtility;
  
              // Act
              host.DecorateRazorParser(parser, rootedFilePath);
  
              // Assert
              Assert.Equal("src/file.cshtml", chunkInheritanceUtility.InheritedChunkTreePagePath, StringComparer.Ordinal);
          }
  
          [Theory]
          [InlineData("//")]
          [InlineData("C:/")]
          [InlineData(@"\\")]
          [InlineData(@"C:\")]
          public void DecorateCodeGenerator_DesignTimeRazorPathNormalizer_NormalizesChunkInheritanceUtilityPaths(
              string rootPrefix)
          {
              // Arrange
              var rootedAppPath = $"{rootPrefix}SomeComputer/Location/Project/";
              var rootedFilePath = $"{rootPrefix}SomeComputer/Location/Project/src/file.cshtml";
              var host = new MvcRazorHost(
                  chunkTreeCache: null,
                  pathNormalizer: new DesignTimeRazorPathNormalizer(rootedAppPath));
              var chunkInheritanceUtility = new PathValidatingChunkInheritanceUtility(host);
              var codeGeneratorContext = new CodeGeneratorContext(
                  new ChunkGeneratorContext(
                      host,
                      host.DefaultClassName,
                      host.DefaultNamespace,
                      rootedFilePath,
                      shouldGenerateLinePragmas: true),
                  new ErrorSink());
              var codeGenerator = new CSharpCodeGenerator(codeGeneratorContext);
              host.ChunkInheritanceUtility = chunkInheritanceUtility;
  
              // Act
              host.DecorateCodeGenerator(codeGenerator, codeGeneratorContext);
  
              // Assert
              Assert.Equal("src/file.cshtml", chunkInheritanceUtility.InheritedChunkTreePagePath, StringComparer.Ordinal);
          }
  
          [Fact]
          public void MvcRazorHost_EnablesInstrumentationByDefault()
          {
              // Arrange
              var fileProvider = new TestFileProvider();
              var host = new MvcRazorHost(new DefaultChunkTreeCache(fileProvider));
  
              // Act
              var instrumented = host.EnableInstrumentation;
  
              // Assert
              Assert.True(instrumented);
          }
  
          [Fact]
          public void MvcRazorHost_GeneratesTagHelperModelExpressionCode_DesignTime()
          {
              // Arrange
              var fileProvider = new TestFileProvider();
              var host = new MvcRazorHost(new DefaultChunkTreeCache(fileProvider))
              {
                  DesignTimeMode = true
              };
              var expectedLineMappings = new List<LineMapping>
              {
                  BuildLineMapping(documentAbsoluteIndex: 7,
                                   documentLineIndex: 0,
                                   documentCharacterIndex: 7,
                                   generatedAbsoluteIndex: 444,
                                   generatedLineIndex: 12,
                                   generatedCharacterIndex: 7,
                                   contentLength: 8),
                  BuildLineMapping(documentAbsoluteIndex: 33,
                                   documentLineIndex: 2,
                                   documentCharacterIndex: 14,
                                   generatedAbsoluteIndex: 823,
                                   generatedLineIndex: 25,
                                   generatedCharacterIndex: 14,
                                   contentLength: 85),
                  BuildLineMapping(documentAbsoluteIndex: 139,
                                   documentLineIndex: 4,
                                   documentCharacterIndex: 17,
                                   generatedAbsoluteIndex: 2313,
                                   generatedLineIndex: 55,
                                   generatedCharacterIndex: 95,
                                   contentLength: 3),
                  BuildLineMapping(
                      documentAbsoluteIndex: 166,
                      documentLineIndex: 5,
                      documentCharacterIndex: 18,
                      generatedAbsoluteIndex: 2626,
                      generatedLineIndex: 61,
                      generatedCharacterIndex: 87,
                      contentLength: 5),
              };
  
              // Act and Assert
              RunDesignTimeTest(host,
                                testName: "ModelExpressionTagHelper",
                                expectedLineMappings: expectedLineMappings);
          }
  
          [Theory]
          [InlineData("Basic")]
          [InlineData("Inject")]
          [InlineData("InjectWithModel")]
          [InlineData("InjectWithSemicolon")]
          [InlineData("Model")]
          [InlineData("ModelExpressionTagHelper")]
          public void MvcRazorHost_ParsesAndGeneratesCodeForBasicScenarios(string scenarioName)
          {
              // Arrange
              var fileProvider = new TestFileProvider();
              var host = new TestMvcRazorHost(new DefaultChunkTreeCache(fileProvider));
  
              // Act and Assert
              RunRuntimeTest(host, scenarioName);
          }
  
          [Fact]
          public void BasicVisitor_GeneratesCorrectLineMappings()
          {
              // Arrange
              var fileProvider = new TestFileProvider();
              var host = new MvcRazorHost(new DefaultChunkTreeCache(fileProvider))
              {
                  DesignTimeMode = true
              };
              host.NamespaceImports.Clear();
              var expectedLineMappings = new[]
              {
                  BuildLineMapping(
                      documentAbsoluteIndex: 13,
                      documentLineIndex: 0,
                      documentCharacterIndex: 13,
                      generatedAbsoluteIndex: 1269,
                      generatedLineIndex: 32,
                      generatedCharacterIndex: 13,
                      contentLength: 4),
                  BuildLineMapping(
                      documentAbsoluteIndex: 43,
                      documentLineIndex: 2,
                      documentCharacterIndex: 5,
                      generatedAbsoluteIndex: 1353,
                      generatedLineIndex: 37,
                      generatedCharacterIndex: 6,
                      contentLength: 21),
              };
  
              // Act and Assert
              RunDesignTimeTest(host, "Basic", expectedLineMappings);
          }
  
          [Fact]
          public void InjectVisitor_GeneratesCorrectLineMappings()
          {
              // Arrange
              var fileProvider = new TestFileProvider();
              var host = new MvcRazorHost(new DefaultChunkTreeCache(fileProvider))
              {
                  DesignTimeMode = true
              };
              host.NamespaceImports.Clear();
              var expectedLineMappings = new List<LineMapping>
              {
                  BuildLineMapping(1, 0, 1, 59, 3, 0, 17),
                  BuildLineMapping(28, 1, 8, 706, 26, 8, 20)
              };
  
              // Act and Assert
              RunDesignTimeTest(host, "Inject", expectedLineMappings);
          }
  
          [Fact]
          public void InjectVisitorWithModel_GeneratesCorrectLineMappings()
          {
              // Arrange
  
gt:             var fileProvider = new TestFileProvider();