Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow usage of alias before anchor declaration #491

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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>(@"
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>>(@"
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