public void FormatMessage_caches_reused_pattern()
        {
            var parserMock = new Mock<IPatternParser>();
            var realParser = new PatternParser(new LiteralParser());
            parserMock.Setup(x => x.Parse(It.IsAny<StringBuilder>()))
                      .Returns((StringBuilder sb) => realParser.Parse(sb));
            var library = new FormatterLibrary();

            var subject = new MessageFormatter(patternParser: parserMock.Object, library: library, useCache: true);

            var pattern = "Hi {gender, select, male {Sir} female {Ma'am}}!";
            var actual = subject.FormatMessage(pattern, new { gender = "male" });
            Assert.Equal("Hi Sir!", actual);

            // '2' because it did not format "Ma'am" yet.
            parserMock.Verify(x => x.Parse(It.IsAny<StringBuilder>()), Times.Exactly(2));

            actual = subject.FormatMessage(pattern, new { gender = "female" });
            Assert.Equal("Hi Ma'am!", actual);
            parserMock.Verify(x => x.Parse(It.IsAny<StringBuilder>()), Times.Exactly(3));

            // '3' because it has cached all options
            actual = subject.FormatMessage(pattern, new { gender = "female" });
            Assert.Equal("Hi Ma'am!", actual);
            parserMock.Verify(x => x.Parse(It.IsAny<StringBuilder>()), Times.Exactly(3));
        }
        public void Parse()
        {
            var subject = new PatternParser(new LiteralParser());

            const string source = @"Hi, {Name, select,
                                male={guy} female={gal}}, you have {count, plural, 
                                zero {no friends}, other {# friends}
                                }";
            Benchmark.Start("First run (warm-up)", this.outputHelper);
            subject.Parse(new StringBuilder(source));
            Benchmark.End(this.outputHelper);

            Benchmark.Start("Next one (warmed up)", this.outputHelper);
            var actual = subject.Parse(new StringBuilder(source));
            Benchmark.End(this.outputHelper);
            Assert.Equal(2, actual.Count());
            var formatterParam = actual.First();
            Assert.Equal("Name", formatterParam.Variable);
            Assert.Equal("select", formatterParam.FormatterName);
            Assert.Equal("male={guy} female={gal}", formatterParam.FormatterArguments);

            formatterParam = actual.ElementAt(1);
            Assert.Equal("count", formatterParam.Variable);
            Assert.Equal("plural", formatterParam.FormatterName);
            Assert.Equal("zero {no friends}, other {# friends}", formatterParam.FormatterArguments);
        }
 public void Parse_exits_early_when_no_literals_have_been_found()
 {
     var literalParserMock = new Mock<ILiteralParser>();
     var subject = new PatternParser(literalParserMock.Object);
     literalParserMock.Setup(x => x.ParseLiterals(It.IsAny<StringBuilder>())).Returns(new Literal[0]);
     Assert.Empty(subject.Parse(new StringBuilder()));
 }
        public void Parse(string source, string expectedKey, string expectedFormat, string expectedArgs)
        {
            var literalParserMock = new Mock<ILiteralParser>();
            var sb = new StringBuilder(source);
            literalParserMock.Setup(x => x.ParseLiterals(sb));
            literalParserMock.Setup(x => x.ParseLiterals(sb))
                             .Returns(new[] { new Literal(0, source.Length, 1, 1, new StringBuilder(source)) });

            var subject = new PatternParser(literalParserMock.Object);

            // Warm up (JIT)
            Benchmark.Start("Parsing formatter patterns (first time before JIT)", this.outputHelper);
            subject.Parse(sb);
            Benchmark.End(this.outputHelper);
            Benchmark.Start("Parsing formatter patterns (after warm-up)", this.outputHelper);
            var actual = subject.Parse(sb);
            Benchmark.End(this.outputHelper);
            Assert.Equal(1, actual.Count());
            var first = actual.First();
            Assert.Equal(expectedKey, first.Variable);
            Assert.Equal(expectedFormat, first.FormatterName);
            Assert.Equal(expectedArgs, first.FormatterArguments);
        }