Skip to content

Commit

Permalink
Merge pull request #179 from aaubry/newline-handling
Browse files Browse the repository at this point in the history
Improve newline handling
  • Loading branch information
aaubry committed May 31, 2016
2 parents d447128 + 3f19d1d commit 45da90c
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 81 deletions.
23 changes: 23 additions & 0 deletions YamlDotNet.Test/Core/EmitterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,29 @@ public void EmptyStringsAreQuoted()
.Contain("- ''");
}

[Theory]
[InlineData("b-carriage-return,b-line-feed\r\nlll", "b-carriage-return,b-line-feed\nlll")]
[InlineData("b-carriage-return\rlll", "b-carriage-return\nlll")]
[InlineData("b-line-feed\nlll", "b-line-feed\nlll")]
[InlineData("b-next-line\x85lll", "b-next-line\nlll")]
[InlineData("b-line-separator\x2028lll", "b-line-separator\x2028lll")]
[InlineData("b-paragraph-separator\x2029lll", "b-paragraph-separator\x2029lll")]
public void NewLinesAreNotDuplicatedWhenEmitted(string input, string expected)
{
var yaml = EmittedTextFrom(StreamOf(DocumentWith(
LiteralScalar(input)
)));

var parser = new Parser(new StringReader(yaml));

AssertSequenceOfEventsFrom(Yaml.ParserForText(yaml),
StreamStart,
DocumentStart(Implicit),
LiteralScalar(expected),
DocumentEnd(Implicit),
StreamEnd);
}

private string Lines(params string[] lines)
{
return string.Join(Environment.NewLine, lines);
Expand Down
59 changes: 59 additions & 0 deletions YamlDotNet.Test/Core/EventsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using FluentAssertions;
using System.Collections;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using TagDirective = YamlDotNet.Core.Tokens.TagDirective;
Expand Down Expand Up @@ -273,5 +275,62 @@ public MappingStartBuilder Explicit
return new MappingStart(null, builder.tag, builder.@implicit, builder.style);
}
}

protected void AssertSequenceOfEventsFrom(IParser parser, params ParsingEvent[] events)
{
var eventNumber = 1;
foreach (var expected in events)
{
parser.MoveNext().Should().BeTrue("Missing parse event number {0}", eventNumber);
AssertEvent(expected, parser.Current, eventNumber);
eventNumber++;
}
parser.MoveNext().Should().BeFalse("Found extra parse events");
}

protected void AssertEvent(ParsingEvent expected, ParsingEvent actual, int eventNumber)
{
actual.GetType().Should().Be(expected.GetType(), "Parse event {0} is not of the expected type.", eventNumber);

foreach (var property in expected.GetType().GetProperties())
{
if (property.PropertyType == typeof(Mark) || !property.CanRead)
{
continue;
}

var value = property.GetValue(actual, null);
var expectedValue = property.GetValue(expected, null);
if (expectedValue is IEnumerable && !(expectedValue is string))
{
Dump.Write("\t{0} = {{", property.Name);
Dump.Write(string.Join(", ", (IEnumerable)value));
Dump.WriteLine("}");

if (expectedValue is ICollection && value is ICollection)
{
var expectedCount = ((ICollection)expectedValue).Count;
var valueCount = ((ICollection)value).Count;
valueCount.Should().Be(expectedCount, "Compared size of collections in property {0} in parse event {1}",
property.Name, eventNumber);
}

var values = ((IEnumerable)value).GetEnumerator();
var expectedValues = ((IEnumerable)expectedValue).GetEnumerator();
while (expectedValues.MoveNext())
{
values.MoveNext().Should().BeTrue("Property {0} in parse event {1} had too few elements", property.Name, eventNumber);
values.Current.Should().Be(expectedValues.Current,
"Compared element in property {0} in parse event {1}", property.Name, eventNumber);
}
values.MoveNext().Should().BeFalse("Property {0} in parse event {1} had too many elements", property.Name, eventNumber);
}
else
{
Dump.WriteLine("\t{0} = {1}", property.Name, value);
value.Should().Be(expectedValue, "Compared property {0} in parse event {1}", property.Name, eventNumber);
}
}
}
}
}
80 changes: 20 additions & 60 deletions YamlDotNet.Test/Core/ParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

using FluentAssertions;
using System.Collections;
using System.IO;
using Xunit;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;

namespace YamlDotNet.Test.Core
{
Expand Down Expand Up @@ -367,63 +365,6 @@ public void CommentsAreOmittedUnlessRequested()
StreamEnd);
}

private void AssertSequenceOfEventsFrom(IParser parser, params ParsingEvent[] events)
{
var eventNumber = 1;
foreach (var expected in events)
{
parser.MoveNext().Should().BeTrue("Missing parse event number {0}", eventNumber);
AssertEvent(expected, parser.Current, eventNumber);
eventNumber++;
}
parser.MoveNext().Should().BeFalse("Found extra parse events");
}

private void AssertEvent(ParsingEvent expected, ParsingEvent actual, int eventNumber)
{
actual.GetType().Should().Be(expected.GetType(), "Parse event {0} is not of the expected type.", eventNumber);

foreach (var property in expected.GetType().GetProperties())
{
if (property.PropertyType == typeof(Mark) || !property.CanRead)
{
continue;
}

var value = property.GetValue(actual, null);
var expectedValue = property.GetValue(expected, null);
if (expectedValue is IEnumerable && !(expectedValue is string))
{
Dump.Write("\t{0} = {{", property.Name);
Dump.Write(string.Join(", ", (IEnumerable)value));
Dump.WriteLine("}");

if (expectedValue is ICollection && value is ICollection)
{
var expectedCount = ((ICollection)expectedValue).Count;
var valueCount = ((ICollection)value).Count;
valueCount.Should().Be(expectedCount, "Compared size of collections in property {0} in parse event {1}",
property.Name, eventNumber);
}

var values = ((IEnumerable)value).GetEnumerator();
var expectedValues = ((IEnumerable)expectedValue).GetEnumerator();
while (expectedValues.MoveNext())
{
values.MoveNext().Should().BeTrue("Property {0} in parse event {1} had too few elements", property.Name, eventNumber);
values.Current.Should().Be(expectedValues.Current,
"Compared element in property {0} in parse event {1}", property.Name, eventNumber);
}
values.MoveNext().Should().BeFalse("Property {0} in parse event {1} had too many elements", property.Name, eventNumber);
}
else
{
Dump.WriteLine("\t{0} = {1}", property.Name, value);
value.Should().Be(expectedValue, "Compared property {0} in parse event {1}", property.Name, eventNumber);
}
}
}

[Fact]
public void VerifyTokenWithMultiDocTag()
{
Expand All @@ -446,5 +387,24 @@ public void VerifyTokenWithMultiDocTag()
DocumentEnd(Implicit),
StreamEnd);
}

[Theory]
[InlineData("|\n b-carriage-return,b-line-feed\r\n lll", "b-carriage-return,b-line-feed\nlll")]
[InlineData("|\n b-carriage-return\r lll", "b-carriage-return\nlll")]
[InlineData("|\n b-line-feed\n lll", "b-line-feed\nlll")]
[InlineData("|\n b-next-line\x85 lll", "b-next-line\nlll")]
[InlineData("|\n b-line-separator\x2028 lll", "b-line-separator\x2028lll")]
[InlineData("|\n b-paragraph-separator\x2029 lll", "b-paragraph-separator\x2029lll")]
public void NewLinesAreParsedAccordingToTheSpecification(string yaml, string expected)
{
var parser = new Parser(new StringReader(yaml));

AssertSequenceOfEventsFrom(Yaml.ParserForText(yaml),
StreamStart,
DocumentStart(Implicit),
LiteralScalar(expected),
DocumentEnd(Implicit),
StreamEnd);
}
}
}
2 changes: 1 addition & 1 deletion YamlDotNet.Test/Yaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public static StringReader ReaderForText(string yamlText)

if (lines.Count > 0)
{
var indent = Regex.Match(lines[0], @"^(\s+)");
var indent = Regex.Match(lines[0], @"^(\s*)");
if (!indent.Success)
{
throw new ArgumentException("Invalid indentation");
Expand Down

0 comments on commit 45da90c

Please sign in to comment.