/test/System.Web.Razor.Test/Framework/ParserTestBase.cs
C# | 381 lines | 326 code | 47 blank | 8 comment | 34 complexity | 35e13fcac4e9fb26ed63e4e6b67dc559 MD5 | raw file
- //#define PARSER_TRACE
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Text;
- using System.Web.Razor.Generator;
- using System.Web.Razor.Parser;
- using System.Web.Razor.Parser.SyntaxTree;
- using System.Web.Razor.Text;
- using Xunit;
- namespace System.Web.Razor.Test.Framework
- {
- public abstract class ParserTestBase
- {
- protected static Block IgnoreOutput = new IgnoreOutputBlock();
- public SpanFactory Factory { get; private set; }
- protected ParserTestBase()
- {
- Factory = CreateSpanFactory();
- }
- public abstract ParserBase CreateMarkupParser();
- public abstract ParserBase CreateCodeParser();
- protected abstract ParserBase SelectActiveParser(ParserBase codeParser, ParserBase markupParser);
- public virtual ParserContext CreateParserContext(ITextDocument input, ParserBase codeParser, ParserBase markupParser)
- {
- return new ParserContext(input, codeParser, markupParser, SelectActiveParser(codeParser, markupParser));
- }
- protected abstract SpanFactory CreateSpanFactory();
- protected virtual void ParseBlockTest(string document)
- {
- ParseBlockTest(document, null, false, new RazorError[0]);
- }
- protected virtual void ParseBlockTest(string document, bool designTimeParser)
- {
- ParseBlockTest(document, null, designTimeParser, new RazorError[0]);
- }
- protected virtual void ParseBlockTest(string document, params RazorError[] expectedErrors)
- {
- ParseBlockTest(document, false, expectedErrors);
- }
- protected virtual void ParseBlockTest(string document, bool designTimeParser, params RazorError[] expectedErrors)
- {
- ParseBlockTest(document, null, designTimeParser, expectedErrors);
- }
- protected virtual void ParseBlockTest(string document, Block expectedRoot)
- {
- ParseBlockTest(document, expectedRoot, false, null);
- }
- protected virtual void ParseBlockTest(string document, Block expectedRoot, bool designTimeParser)
- {
- ParseBlockTest(document, expectedRoot, designTimeParser, null);
- }
- protected virtual void ParseBlockTest(string document, Block expectedRoot, params RazorError[] expectedErrors)
- {
- ParseBlockTest(document, expectedRoot, false, expectedErrors);
- }
- protected virtual void ParseBlockTest(string document, Block expectedRoot, bool designTimeParser, params RazorError[] expectedErrors)
- {
- RunParseTest(document, parser => parser.ParseBlock, expectedRoot, (expectedErrors ?? new RazorError[0]).ToList(), designTimeParser);
- }
- protected virtual void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
- {
- SingleSpanBlockTest(document, blockType, spanType, acceptedCharacters, expectedError: null);
- }
- protected virtual void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
- {
- SingleSpanBlockTest(document, spanContent, blockType, spanType, acceptedCharacters, expectedErrors: null);
- }
- protected virtual void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, params RazorError[] expectedError)
- {
- SingleSpanBlockTest(document, document, blockType, spanType, expectedError);
- }
- protected virtual void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, params RazorError[] expectedErrors)
- {
- SingleSpanBlockTest(document, spanContent, blockType, spanType, AcceptedCharacters.Any, expectedErrors ?? new RazorError[0]);
- }
- protected virtual void SingleSpanBlockTest(string document, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters, params RazorError[] expectedError)
- {
- SingleSpanBlockTest(document, document, blockType, spanType, acceptedCharacters, expectedError);
- }
- protected virtual void SingleSpanBlockTest(string document, string spanContent, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters, params RazorError[] expectedErrors)
- {
- BlockBuilder builder = new BlockBuilder();
- builder.Type = blockType;
- ParseBlockTest(
- document,
- ConfigureAndAddSpanToBlock(
- builder,
- Factory.Span(spanType, spanContent, spanType == SpanKind.Markup)
- .Accepts(acceptedCharacters)),
- expectedErrors ?? new RazorError[0]);
- }
- protected virtual ParserResults RunParse(string document, Func<ParserBase, Action> parserActionSelector, bool designTimeParser)
- {
- // Create the source
- ParserResults results = null;
- using (SeekableTextReader reader = new SeekableTextReader(document))
- {
- try
- {
- ParserBase codeParser = CreateCodeParser();
- ParserBase markupParser = CreateMarkupParser();
- ParserContext context = CreateParserContext(reader, codeParser, markupParser);
- context.DesignTimeMode = designTimeParser;
- codeParser.Context = context;
- markupParser.Context = context;
- // Run the parser
- parserActionSelector(context.ActiveParser)();
- results = context.CompleteParse();
- }
- finally
- {
- if (results != null && results.Document != null)
- {
- WriteTraceLine(String.Empty);
- WriteTraceLine("Actual Parse Tree:");
- WriteNode(0, results.Document);
- }
- }
- }
- return results;
- }
- protected virtual void RunParseTest(string document, Func<ParserBase, Action> parserActionSelector, Block expectedRoot, IList<RazorError> expectedErrors, bool designTimeParser)
- {
- // Create the source
- ParserResults results = RunParse(document, parserActionSelector, designTimeParser);
- // Evaluate the results
- if (!ReferenceEquals(expectedRoot, IgnoreOutput))
- {
- EvaluateResults(results, expectedRoot, expectedErrors);
- }
- }
- [Conditional("PARSER_TRACE")]
- private void WriteNode(int indent, SyntaxTreeNode node)
- {
- string content = node.ToString().Replace("\r", "\\r")
- .Replace("\n", "\\n")
- .Replace("{", "{{")
- .Replace("}", "}}");
- if (indent > 0)
- {
- content = new String('.', indent * 2) + content;
- }
- WriteTraceLine(content);
- Block block = node as Block;
- if (block != null)
- {
- foreach (SyntaxTreeNode child in block.Children)
- {
- WriteNode(indent + 1, child);
- }
- }
- }
- public static void EvaluateResults(ParserResults results, Block expectedRoot)
- {
- EvaluateResults(results, expectedRoot, null);
- }
- public static void EvaluateResults(ParserResults results, Block expectedRoot, IList<RazorError> expectedErrors)
- {
- EvaluateParseTree(results.Document, expectedRoot);
- EvaluateRazorErrors(results.ParserErrors, expectedErrors);
- }
- public static void EvaluateParseTree(Block actualRoot, Block expectedRoot)
- {
- // Evaluate the result
- ErrorCollector collector = new ErrorCollector();
- // Link all the nodes
- expectedRoot.LinkNodes();
- if (expectedRoot == null)
- {
- Assert.Null(actualRoot);
- }
- else
- {
- Assert.NotNull(actualRoot);
- EvaluateSyntaxTreeNode(collector, actualRoot, expectedRoot);
- if (collector.Success)
- {
- WriteTraceLine("Parse Tree Validation Succeeded:\r\n{0}", collector.Message);
- }
- else
- {
- Assert.True(false, String.Format("\r\n{0}", collector.Message));
- }
- }
- }
- private static void EvaluateSyntaxTreeNode(ErrorCollector collector, SyntaxTreeNode actual, SyntaxTreeNode expected)
- {
- if (actual == null)
- {
- AddNullActualError(collector, actual, expected);
- }
- if (actual.IsBlock != expected.IsBlock)
- {
- AddMismatchError(collector, actual, expected);
- }
- else
- {
- if (expected.IsBlock)
- {
- EvaluateBlock(collector, (Block)actual, (Block)expected);
- }
- else
- {
- EvaluateSpan(collector, (Span)actual, (Span)expected);
- }
- }
- }
- private static void EvaluateSpan(ErrorCollector collector, Span actual, Span expected)
- {
- if (!Equals(expected, actual))
- {
- AddMismatchError(collector, actual, expected);
- }
- else
- {
- AddPassedMessage(collector, expected);
- }
- }
- private static void EvaluateBlock(ErrorCollector collector, Block actual, Block expected)
- {
- if (actual.Type != expected.Type || !expected.CodeGenerator.Equals(actual.CodeGenerator))
- {
- AddMismatchError(collector, actual, expected);
- }
- else
- {
- AddPassedMessage(collector, expected);
- using (collector.Indent())
- {
- IEnumerator<SyntaxTreeNode> expectedNodes = expected.Children.GetEnumerator();
- IEnumerator<SyntaxTreeNode> actualNodes = actual.Children.GetEnumerator();
- while (expectedNodes.MoveNext())
- {
- if (!actualNodes.MoveNext())
- {
- collector.AddError("{0} - FAILED :: No more elements at this node", expectedNodes.Current);
- }
- else
- {
- EvaluateSyntaxTreeNode(collector, actualNodes.Current, expectedNodes.Current);
- }
- }
- while (actualNodes.MoveNext())
- {
- collector.AddError("End of Node - FAILED :: Found Node: {0}", actualNodes.Current);
- }
- }
- }
- }
- private static void AddPassedMessage(ErrorCollector collector, SyntaxTreeNode expected)
- {
- collector.AddMessage("{0} - PASSED", expected);
- }
- private static void AddMismatchError(ErrorCollector collector, SyntaxTreeNode actual, SyntaxTreeNode expected)
- {
- collector.AddError("{0} - FAILED :: Actual: {1}", expected, actual);
- }
- private static void AddNullActualError(ErrorCollector collector, SyntaxTreeNode actual, SyntaxTreeNode expected)
- {
- collector.AddError("{0} - FAILED :: Actual: << Null >>", expected);
- }
- public static void EvaluateRazorErrors(IList<RazorError> actualErrors, IList<RazorError> expectedErrors)
- {
- // Evaluate the errors
- if (expectedErrors == null || expectedErrors.Count == 0)
- {
- Assert.True(actualErrors.Count == 0,
- String.Format("Expected that no errors would be raised, but the following errors were:\r\n{0}", FormatErrors(actualErrors)));
- }
- else
- {
- Assert.True(expectedErrors.Count == actualErrors.Count,
- String.Format("Expected that {0} errors would be raised, but {1} errors were.\r\nExpected Errors: \r\n{2}\r\nActual Errors: \r\n{3}",
- expectedErrors.Count,
- actualErrors.Count,
- FormatErrors(expectedErrors),
- FormatErrors(actualErrors)));
- Assert.Equal(expectedErrors.ToArray(), actualErrors.ToArray());
- }
- WriteTraceLine("Expected Errors were raised:\r\n{0}", FormatErrors(expectedErrors));
- }
- public static string FormatErrors(IList<RazorError> errors)
- {
- if (errors == null)
- {
- return "\t<< No Errors >>";
- }
- StringBuilder builder = new StringBuilder();
- foreach (RazorError err in errors)
- {
- builder.AppendFormat("\t{0}", err);
- builder.AppendLine();
- }
- return builder.ToString();
- }
- [Conditional("PARSER_TRACE")]
- private static void WriteTraceLine(string format, params object[] args)
- {
- Trace.WriteLine(String.Format(format, args));
- }
- protected virtual Block CreateSimpleBlockAndSpan(string spanContent, BlockType blockType, SpanKind spanType, AcceptedCharacters acceptedCharacters = AcceptedCharacters.Any)
- {
- SpanConstructor span = Factory.Span(spanType, spanContent, spanType == SpanKind.Markup).Accepts(acceptedCharacters);
- BlockBuilder b = new BlockBuilder()
- {
- Type = blockType
- };
- return ConfigureAndAddSpanToBlock(b, span);
- }
- protected virtual Block ConfigureAndAddSpanToBlock(BlockBuilder block, SpanConstructor span)
- {
- switch (block.Type)
- {
- case BlockType.Markup:
- span.With(new MarkupCodeGenerator());
- break;
- case BlockType.Statement:
- span.With(new StatementCodeGenerator());
- break;
- case BlockType.Expression:
- block.CodeGenerator = new ExpressionCodeGenerator();
- span.With(new ExpressionCodeGenerator());
- break;
- }
- block.Children.Add(span);
- return block.Build();
- }
- private class IgnoreOutputBlock : Block
- {
- public IgnoreOutputBlock() : base(BlockType.Template, Enumerable.Empty<SyntaxTreeNode>(), null) { }
- }
- }
- }