Skip to content

Commit

Permalink
Disallow usage of alias before anchor declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
am11 committed May 10, 2020
1 parent 49bda13 commit 9c769a6
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
Expand Up @@ -233,19 +233,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 @@ -511,30 +498,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 @@ -612,47 +575,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 @@ -1562,6 +1484,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>(Yaml.ReaderForText(@"
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 @@ -1789,6 +1743,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>>(Yaml.ReaderForText(@"
a: *anchor1
b: &anchor1 test0
c: *anchor1"));

action.ShouldThrow<AnchorNotFoundException>();
}

[Fact]
public void AnchorWithAllowedCharactersCanBeDeserialized()
{
Expand Down
Expand Up @@ -104,8 +104,7 @@ public ValuePromise(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 9c769a6

Please sign in to comment.