Skip to content

Commit b759707

Browse files
authored
Merge pull request #1086 from fdcastel/fix-todos-typos
Fix TODOs, typos, and add missing tests +semver:fix
2 parents 8383b30 + b887a0f commit b759707

14 files changed

Lines changed: 169 additions & 19 deletions

YamlDotNet.Test/Serialization/DeserializerTest.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,45 @@ public class RequiredMemberClass
611611
public required string Field = string.Empty;
612612
public required string Property { get; set; } = string.Empty;
613613
}
614+
615+
[Fact]
616+
public void WithRequiredMemberSet_ThrowsWhenBothMissing_ListsBothNames()
617+
{
618+
var deserializer = new DeserializerBuilder()
619+
.WithEnforceRequiredMembers()
620+
.IgnoreUnmatchedProperties()
621+
.Build();
622+
var yaml = "UnrelatedKey: irrelevant";
623+
var ex = Assert.Throws<YamlException>(() =>
624+
{
625+
deserializer.Deserialize<RequiredMemberClass>(yaml);
626+
});
627+
Assert.Contains("Field", ex.Message);
628+
Assert.Contains("Property", ex.Message);
629+
}
630+
631+
[Fact]
632+
public void WithRequiredMemberSet_ThrowsWithDescriptiveMessage()
633+
{
634+
var deserializer = new DeserializerBuilder().WithEnforceRequiredMembers().Build();
635+
var yaml = "Property: test";
636+
var ex = Assert.Throws<YamlException>(() =>
637+
{
638+
deserializer.Deserialize<RequiredMemberClass>(yaml);
639+
});
640+
Assert.Contains("Missing properties", ex.Message);
641+
Assert.Contains("Field", ex.Message);
642+
}
643+
644+
[Fact]
645+
public void WithoutEnforceRequiredMembers_DoesNotThrowWhenMissing()
646+
{
647+
// When enforcement is NOT enabled, missing required members should not throw
648+
var deserializer = new DeserializerBuilder().Build();
649+
var yaml = "Property: test";
650+
var actual = deserializer.Deserialize<RequiredMemberClass>(yaml);
651+
Assert.Equal("test", actual.Property);
652+
}
614653
#endif
615654

616655
#if NET6_0_OR_GREATER
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// This file is part of YamlDotNet - A .NET library for YAML.
2+
// Copyright (c) Antoine Aubry and contributors
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
// this software and associated documentation files (the "Software"), to deal in
6+
// the Software without restriction, including without limitation the rights to
7+
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8+
// of the Software, and to permit persons to whom the Software is furnished to do
9+
// so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
using System;
23+
using FluentAssertions;
24+
using Xunit;
25+
using YamlDotNet.Core;
26+
using YamlDotNet.Serialization;
27+
28+
namespace YamlDotNet.Test.Serialization
29+
{
30+
public class ScalarNodeDeserializerTests
31+
{
32+
private readonly IDeserializer deserializer = new DeserializerBuilder().Build();
33+
34+
[Theory]
35+
[InlineData("2024-01-15")]
36+
[InlineData("2024-12-31T23:59:59Z")]
37+
[InlineData("2024-06-15T10:30:00")]
38+
public void DateTime_ParsesValidValues(string yamlValue)
39+
{
40+
var result = deserializer.Deserialize<DateTime>(yamlValue);
41+
result.Should().BeAfter(DateTime.MinValue);
42+
}
43+
44+
[Theory]
45+
[InlineData("not-a-date")]
46+
[InlineData("hello world")]
47+
public void DateTime_ThrowsOnInvalidValues(string yamlValue)
48+
{
49+
Action act = () => deserializer.Deserialize<DateTime>(yamlValue);
50+
act.Should().Throw<YamlException>();
51+
}
52+
53+
[Theory]
54+
[InlineData("1:00:00", 3600)] // 1 hour = 3600 seconds
55+
[InlineData("1:30", 90)] // 1*60 + 30 = 90
56+
[InlineData("1:00", 60)] // 1*60 + 0 = 60
57+
public void Base60Integer_ParsesValidValues(string yamlValue, int expected)
58+
{
59+
var result = deserializer.Deserialize<int>(yamlValue);
60+
result.Should().Be(expected);
61+
}
62+
63+
[Fact]
64+
public void Base60Integer_RejectsInvalidSexagesimalDigit()
65+
{
66+
// 1:99 is invalid because 99 >= 60
67+
Action act = () => deserializer.Deserialize<int>("1:99");
68+
act.Should().Throw<YamlException>()
69+
.WithInnerException<FormatException>()
70+
.WithMessage("*sexagesimal*less than 60*");
71+
}
72+
73+
[Fact]
74+
public void Base60Integer_AllowsFirstChunkAbove59()
75+
{
76+
// The first chunk can be any value (it's the most significant digit)
77+
// 100:30 = 100*60 + 30 = 6030
78+
var result = deserializer.Deserialize<int>("100:30");
79+
result.Should().Be(6030);
80+
}
81+
82+
[Fact]
83+
public void Base60Integer_RejectsSecondChunkOf60()
84+
{
85+
// 1:60 is invalid because 60 >= 60
86+
Action act = () => deserializer.Deserialize<int>("1:60");
87+
act.Should().Throw<YamlException>()
88+
.WithInnerException<FormatException>()
89+
.WithMessage("*sexagesimal*less than 60*");
90+
}
91+
92+
[Theory]
93+
[InlineData("0b1010", 10)] // binary
94+
[InlineData("0b11111111", 255)] // binary 255
95+
[InlineData("010", 8)] // octal
96+
[InlineData("0x1F", 31)] // hex
97+
[InlineData("0xFF", 255)] // hex
98+
public void IntegerBases_ParseCorrectly(string yamlValue, int expected)
99+
{
100+
var result = deserializer.Deserialize<int>(yamlValue);
101+
result.Should().Be(expected);
102+
}
103+
}
104+
}

YamlDotNet.Test/Serialization/SerializationTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,9 @@ public void DeserializeScalarHexNumber()
161161
[Fact]
162162
public void DeserializeScalarLongBase60Number()
163163
{
164-
var result = Deserializer.Deserialize<long>(UsingReaderFor("99_:_58:47:3:6_2:10"));
164+
var result = Deserializer.Deserialize<long>(UsingReaderFor("99_:_58:47:3:5_2:10"));
165165

166-
result.Should().Be(77744246530L);
166+
result.Should().Be(77744245930L);
167167
}
168168

169169
[Theory]

YamlDotNet/Serialization/Converters/DateTime8601Converter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public override object ReadYaml(IParser parser, Type type, ObjectDeserializer ro
7171
/// <param name="emitter"><see cref="IEmitter"/> instance.</param>
7272
/// <param name="value">Value to write.</param>
7373
/// <param name="type"><see cref="Type"/> to convert.</param>
74-
/// <param name="serializer">A serializer to serializer complext objects.</param>
74+
/// <param name="serializer">A serializer to serialize complex objects.</param>
7575
/// <remarks>On serializing, the first format in the list is used.</remarks>
7676
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
7777
{

YamlDotNet/Serialization/Converters/DateTimeConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public override object ReadYaml(IParser parser, Type type, ObjectDeserializer ro
7878
/// <param name="emitter"><see cref="IEmitter"/> instance.</param>
7979
/// <param name="value">Value to write.</param>
8080
/// <param name="type"><see cref="Type"/> to convert.</param>
81-
/// <param name="serializer">A serializer to serializer complext objects.</param>
81+
/// <param name="serializer">A serializer to serialize complex objects.</param>
8282
/// <remarks>On serializing, the first format in the list is used.</remarks>
8383
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
8484
{

YamlDotNet/Serialization/Converters/DateTimeOffsetConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public override object ReadYaml(IParser parser, Type type, ObjectDeserializer ro
8181
/// <param name="emitter"><see cref="IEmitter"/> instance.</param>
8282
/// <param name="value">Value to write.</param>
8383
/// <param name="type"><see cref="Type"/> to convert.</param>
84-
/// <param name="serializer">A serializer to serializer complext objects.</param>
84+
/// <param name="serializer">A serializer to serialize complex objects.</param>
8585
/// <remarks>On serializing, the first format in the list is used.</remarks>
8686
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
8787
{

YamlDotNet/Serialization/Converters/TimeOnlyConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public override object ReadYaml(IParser parser, Type type, ObjectDeserializer ro
7474
/// <param name="emitter"><see cref="IEmitter"/> instance.</param>
7575
/// <param name="value">Value to write.</param>
7676
/// <param name="type"><see cref="Type"/> to convert.</param>
77-
/// <param name="serializer">A serializer to serializer complext objects.</param>
77+
/// <param name="serializer">A serializer to serialize complex objects.</param>
7878
/// <remarks>On serializing, the first format in the list is used.</remarks>
7979
public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
8080
{

YamlDotNet/Serialization/DeserializerBuilder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ public override DeserializerBuilder WithTagMapping(TagName tag, Type type)
406406
{
407407
if (tag.IsEmpty)
408408
{
409-
throw new ArgumentException("Non-specific tags cannot be maped");
409+
throw new ArgumentException("Non-specific tags cannot be mapped");
410410
}
411411

412412
if (type == null)
@@ -452,7 +452,7 @@ public DeserializerBuilder WithoutTagMapping(TagName tag)
452452
{
453453
if (tag.IsEmpty)
454454
{
455-
throw new ArgumentException("Non-specific tags cannot be maped");
455+
throw new ArgumentException("Non-specific tags cannot be mapped");
456456
}
457457

458458
if (!tagMappings.Remove(tag))

YamlDotNet/Serialization/IObjectDescriptor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public static class ObjectDescriptorExtensions
6161
/// <returns></returns>
6262
public static object NonNullValue(this IObjectDescriptor objectDescriptor)
6363
{
64-
return objectDescriptor.Value ?? throw new InvalidOperationException($"Attempted to use a IObjectDescriptor of type '{objectDescriptor.Type.FullName}' whose Value is null at a point whete it is invalid to do so. This may indicate a bug in YamlDotNet.");
64+
return objectDescriptor.Value ?? throw new InvalidOperationException($"Attempted to use a IObjectDescriptor of type '{objectDescriptor.Type.FullName}' whose Value is null at a point where it is invalid to do so. This may indicate a bug in YamlDotNet.");
6565
}
6666
}
6767
}

YamlDotNet/Serialization/NodeDeserializers/ObjectNodeDeserializer.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,6 @@ public bool Deserialize(IParser parser, Type expectedType, Func<IParser, Type, o
153153

154154
if (enforceRequiredProperties)
155155
{
156-
//TODO: Get properties marked as required on the object
157-
//TODO: Compare those properties agains the consumedObjectProperties, throw if any are missing.
158156
var properties = typeInspector.GetProperties(implementationType, value);
159157
var missingPropertyNames = new List<string>();
160158
foreach (var property in properties)

0 commit comments

Comments
 (0)