Skip to content

Commit

Permalink
Merge aaubry#491 - Disallow usage of alias before anchor declaration
Browse files Browse the repository at this point in the history
+semver:breaking
  • Loading branch information
aaubry authored May 28, 2020
2 parents 3691664 + 75d3a1f commit bd37fab
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 80 deletions.
122 changes: 44 additions & 78 deletions YamlDotNet.Test/Serialization/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,19 +243,6 @@ public void DeserializeConvertible()
result.aaa.Should().Be("[hello, world]");
}

[Fact]
public void DeserializationOfObjectsHandlesForwardReferences()
{
var text = Lines(
"Nothing: *forward",
"MyString: &forward ForwardReference");

var result = Deserializer.Deserialize<Example>(UsingReaderFor(text));

result.ShouldBeEquivalentTo(
new { Nothing = "ForwardReference", MyString = "ForwardReference" }, o => o.ExcludingMissingMembers());
}

[Fact]
public void DeserializationFailsForUndefinedForwardReferences()
{
Expand Down Expand Up @@ -521,30 +508,6 @@ public void DeserializeExplicitList()
.Subject.As<IList<int>>().Should().Equal(3, 4, 5);
}

[Fact]
public void DeserializationOfGenericListsHandlesForwardReferences()
{
var text = Lines(
"- *forward",
"- &forward ForwardReference");

var result = Deserializer.Deserialize<string[]>(UsingReaderFor(text));

result.Should().Equal(new[] { "ForwardReference", "ForwardReference" });
}

[Fact]
public void DeserializationOfNonGenericListsHandlesForwardReferences()
{
var text = Lines(
"- *forward",
"- &forward ForwardReference");

var result = Deserializer.Deserialize<ArrayList>(UsingReaderFor(text));

result.Should().Equal(new[] { "ForwardReference", "ForwardReference" });
}

[Fact]
public void RoundtripList()
{
Expand Down Expand Up @@ -622,47 +585,6 @@ public void RoundtripDictionary()
result.Should().Equal(obj);
}

[Fact]
public void DeserializationOfGenericDictionariesHandlesForwardReferences()
{
var text = Lines(
"key1: *forward",
"*forwardKey: ForwardKeyValue",
"*forward: *forward",
"key2: &forward ForwardReference",
"key3: &forwardKey key4");

var result = Deserializer.Deserialize<Dictionary<string, string>>(UsingReaderFor(text));

result.Should().Equal(new Dictionary<string, string> {
{ "ForwardReference", "ForwardReference" },
{ "key1", "ForwardReference" },
{ "key2", "ForwardReference" },
{ "key4", "ForwardKeyValue" },
{ "key3", "key4" }
});
}

[Fact]
public void DeserializationOfNonGenericDictionariesHandlesForwardReferences()
{
var text = Lines(
"key1: *forward",
"*forwardKey: ForwardKeyValue",
"*forward: *forward",
"key2: &forward ForwardReference",
"key3: &forwardKey key4");

var result = Deserializer.Deserialize<Hashtable>(UsingReaderFor(text));

result.Should().BeEquivalentTo(
Entry("ForwardReference", "ForwardReference"),
Entry("key1", "ForwardReference"),
Entry("key2", "ForwardReference"),
Entry("key4", "ForwardKeyValue"),
Entry("key3", "key4"));
}

[Fact]
public void DeserializeListOfDictionaries()
{
Expand Down Expand Up @@ -1591,6 +1513,38 @@ public void DeserializationOfStreamWithDuplicateAnchorsSucceeds()
Assert.NotNull(deserialized);
}

private sealed class AnchorPrecedence
{
internal sealed class AnchorPrecedenceNested
{
public string b1 { get; set; }
public Dictionary<string, string> b2 { get; set; }
}

public string a { get; set; }
public AnchorPrecedenceNested b { get; set; }
public string c { get; set; }
}

[Fact]
public void DeserializationWithDuplicateAnchorsSucceeds()
{
var sut = new Deserializer();
var deserialized = sut.Deserialize<AnchorPrecedence>(@"
a: &anchor1 test0
b:
b1: &anchor1 test1
b2:
b21: &anchor1 test2
c: *anchor1");

Assert.Equal("test0", deserialized.a);
Assert.Equal("test1", deserialized.b.b1);
Assert.Contains("b21", deserialized.b.b2.Keys);
Assert.Equal("test2", deserialized.b.b2["b21"]);
Assert.Equal("test2", deserialized.c);
}

[Fact]
public void SerializeExceptionWithStackTrace()
{
Expand Down Expand Up @@ -1818,6 +1772,18 @@ public void AnchorNameWithTrailingColonReferencedInKeyCanBeDeserialized()
Assert.Equal(@"anchor "" value """, deserialized["myvalue"]);
}

[Fact]
public void AliasBeforeAnchorCannotBeDeserialized()
{
var sut = new Deserializer();
Action action = () => sut.Deserialize<GenericTestDictionary<string, string>>(@"
a: *anchor1
b: &anchor1 test0
c: *anchor1");

action.ShouldThrow<AnchorNotFoundException>();
}

[Fact]
public void AnchorWithAllowedCharactersCanBeDeserialized()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ public object? Value
var aliasState = state.Get<AliasState>();
if (!aliasState.TryGetValue(alias.Value, out var valuePromise))
{
valuePromise = new ValuePromise(alias);
aliasState.Add(alias.Value, valuePromise);
throw new AnchorNotFoundException(alias.Start, alias.End, $"Alias ${alias.Value} cannot precede anchor declaration");
}

return valuePromise.HasValue ? valuePromise.Value : valuePromise;
Expand Down

0 comments on commit bd37fab

Please sign in to comment.