Skip to content

Commit

Permalink
cake-buildGH-1547: Fix issue with parsing escaped curly braces in For…
Browse files Browse the repository at this point in the history
…matParser, add tests
  • Loading branch information
kcamp authored and devlead committed Oct 7, 2017
1 parent 3992c03 commit ea7a13a
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 3 deletions.
106 changes: 104 additions & 2 deletions src/Cake.Core.Tests/Unit/Diagnostics/FormatParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,90 @@ public void Returns_Correct_Token_For_Message_With_One_Property()
Assert.Equal(0, ((PropertyToken)result[0]).Position);
}

[Fact]
public void Should_Return_Literal_Tokens_For_Message_With_Nothing_But_Escaped_Braces()
{
// Given, When
var result = FormatParser.Parse("{{}}").ToArray();

// Then
Assert.Equal(2, result.Length);
Assert.IsType<LiteralToken>(result[0]);
Assert.Equal("{", ((LiteralToken)result[0]).Text);
Assert.Equal("}", ((LiteralToken)result[1]).Text);
}

[Fact]
public void Should_Return_Literal_Tokens_For_Message_With_Escaped_Braces_And_Properties()
{
// Given, When
var result = FormatParser.Parse("{{}} {0}").ToArray();

// Then
Assert.Equal(3, result.Length);
Assert.IsType<LiteralToken>(result[0]);
Assert.Equal("{", ((LiteralToken)result[0]).Text);
Assert.Equal("} ", ((LiteralToken)result[1]).Text);

Assert.IsType<PropertyToken>(result[2]);
Assert.Equal(0, ((PropertyToken)result[2]).Position);
Assert.Equal(null, ((PropertyToken)result[2]).Format);
}

[Fact]
public void Should_Return_Literal_Token_For_Unbalanced_Escaped_Opening_Curly_Braces()
{
// Given, When
var result = FormatParser.Parse("{{ test {0}").ToArray();

// Then
Assert.Equal(3, result.Length);
Assert.IsType<LiteralToken>(result[0]);
Assert.Equal("{", ((LiteralToken)result[0]).Text);
Assert.Equal(" test ", ((LiteralToken)result[1]).Text);

Assert.IsType<PropertyToken>(result[2]);
Assert.Equal(0, ((PropertyToken)result[2]).Position);
Assert.Equal(null, ((PropertyToken)result[2]).Format);
}

[Fact]
public void Should_Return_Literal_Tokens_For_Multiple_Unbalanced_Escaped_Opening_Curly_Braces()
{
// Given, When
var result = FormatParser.Parse("{{{{ test {0}").ToArray();

// Then
Assert.Equal(4, result.Length);
Assert.IsType<LiteralToken>(result[0]);
Assert.Equal("{", ((LiteralToken)result[0]).Text);
Assert.Equal("{", ((LiteralToken)result[1]).Text);
Assert.Equal(" test ", ((LiteralToken)result[2]).Text);

Assert.IsType<PropertyToken>(result[3]);
Assert.Equal(0, ((PropertyToken)result[3]).Position);
Assert.Equal(null, ((PropertyToken)result[3]).Format);
}

[Fact]
public void Should_Return_Literal_Token_For_Unbalanced_Escaped_Closing_Curly_Braces()
{
// Given, When
var result = FormatParser.Parse("test {0:d} }}").ToArray();

// Then
Assert.Equal(3, result.Length);
Assert.IsType<LiteralToken>(result[0]);
Assert.Equal("test ", ((LiteralToken)result[0]).Text);

Assert.IsType<PropertyToken>(result[1]);
Assert.Equal(0, ((PropertyToken)result[1]).Position);
Assert.Equal("d", ((PropertyToken)result[1]).Format);

Assert.IsType<LiteralToken>(result[2]);
Assert.Equal(" }", ((LiteralToken)result[2]).Text);
}

[Fact]
public void Should_Return_Literal_Tokens_For_Message_With_Escaped_Braces()
{
Expand All @@ -56,8 +140,8 @@ public void Should_Return_Literal_Tokens_For_Message_With_Escaped_Braces()
// Then
Assert.Equal(2, result.Length);
Assert.IsType<LiteralToken>(result[0]);
Assert.Equal("{{", ((LiteralToken)result[0]).Text);
Assert.Equal("0}}", ((LiteralToken)result[1]).Text);
Assert.Equal("{", ((LiteralToken)result[0]).Text);
Assert.Equal("0}", ((LiteralToken)result[1]).Text);
}

[Fact]
Expand All @@ -84,6 +168,17 @@ public void Should_Throw_If_A_Format_Item_Is_Not_Positional()
Assert.Equal("Input string was not in a correct format.", result?.Message);
}

[Fact]
public void Should_Throw_If_A_Format_Item_Is_Not_Positional_Even_If_Other_Valid_Tokens_Are_Present()
{
// Given, When
var result = Record.Exception(() => FormatParser.Parse("{} {0}").ToArray());

// Then
Assert.IsType<FormatException>(result);
Assert.Equal("Input string was not in a correct format.", result?.Message);
}

[Fact]
public void Should_Throw_If_A_Format_Item_With_Format_Is_Not_Positional()
{
Expand All @@ -103,10 +198,17 @@ public void Should_Return_Correct_Tokens_For_Message_Which_Mixes_Properties_And_

// Then
Assert.Equal(5, result.Length);

Assert.IsType<LiteralToken>(result[0]);

Assert.IsType<PropertyToken>(result[1]);
Assert.Equal(0, ((PropertyToken)result[1]).Position);

Assert.IsType<LiteralToken>(result[2]);

Assert.IsType<PropertyToken>(result[3]);
Assert.Equal(1, ((PropertyToken)result[3]).Position);

Assert.IsType<LiteralToken>(result[4]);
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/Cake.Core/Diagnostics/Formatting/FormatParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private static FormatToken ParseProperty(TextReader reader)
if ((char)reader.Peek() == '{')
{
reader.Read();
return new LiteralToken("{{");
return new LiteralToken("{");
}
var builder = new StringBuilder();
while (true)
Expand Down Expand Up @@ -106,6 +106,12 @@ private static FormatToken ParseText(TextReader reader)
{
break;
}
if (character == '}' && reader.Peek() == '}')
{
// escaped curly sequence, consume the first character,
// let the iteration/append continue below.
reader.Read();
}
builder.Append((char)reader.Read());
}
return new LiteralToken(builder.ToString());
Expand Down

0 comments on commit ea7a13a

Please sign in to comment.