-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Prevent modifications of the default serialization options instance
MdSerializationOptions.Default provides access to the default serialization options. While the 'Default' field is readonly, the individual settings of the instance could be modified because MdSerializationOptions provides setters for all properties. To prevent such modifications without introducing additional abstractions the property setters will now check if it is allowed to modify the instance and throw when a trying to set a property of the default instance.
- Loading branch information
Showing
2 changed files
with
160 additions
and
13 deletions.
There are no files selected for viewing
80 changes: 80 additions & 0 deletions
80
src/MarkdownGenerator.Test/_Model/_Options/MdSerializationOptionsTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Text; | ||
using Xunit; | ||
|
||
namespace Grynwald.MarkdownGenerator.Test | ||
{ | ||
public class MdSerializationOptionsTest | ||
{ | ||
public static IEnumerable<object[]> Properties() | ||
{ | ||
foreach (var property in typeof(MdSerializationOptions).GetProperties(BindingFlags.Instance | BindingFlags.Public)) | ||
{ | ||
yield return new[] { property.Name }; | ||
} | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(Properties))] | ||
public void Properties_of_the_default_instance_cannot_be_modified(string propertyName) | ||
{ | ||
// ARRANGE | ||
var instance = MdSerializationOptions.Default; | ||
|
||
var property = typeof(MdSerializationOptions).GetProperty(propertyName); | ||
|
||
var testValue = GetTestValue(property.PropertyType); | ||
|
||
// ACT / ASSERT | ||
var exception = Assert.Throws<TargetInvocationException>(() => property.SetMethod.Invoke(instance, new[] { testValue })); | ||
Assert.IsType<InvalidOperationException>(exception.InnerException); | ||
|
||
// exception message should indicate which property cannot be set | ||
Assert.Contains(propertyName, exception.InnerException.Message); | ||
} | ||
|
||
[Theory] | ||
[MemberData(nameof(Properties))] | ||
public void Properties_of_non_default_instance_can_be_modified(string propertyName) | ||
{ | ||
// ARRANGE | ||
var instance = new MdSerializationOptions(); | ||
|
||
var property = typeof(MdSerializationOptions).GetProperty(propertyName); | ||
|
||
var newValue = GetTestValue(property.PropertyType); | ||
|
||
// ACT / ASSERT | ||
property.SetMethod.Invoke(instance, new[] { newValue }); | ||
var actualValue = property.GetMethod.Invoke(instance, Array.Empty<object>()); | ||
Assert.Equal(newValue, actualValue); | ||
} | ||
|
||
|
||
private object GetTestValue(Type type) | ||
{ | ||
if(!type.IsValueType) | ||
{ | ||
return null; | ||
} | ||
|
||
var defaultValue = Activator.CreateInstance(type); | ||
if(type.IsEnum) | ||
{ | ||
var values = Enum.GetValues(type); | ||
if (values.Length <= 1) | ||
return defaultValue; | ||
else | ||
return values.Cast<object>().First(x => !x.Equals(defaultValue)); | ||
} | ||
else | ||
{ | ||
return defaultValue; | ||
} | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters