SerializableConfigurationPropertyTests.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #nullable enable
  2. using System.Reflection;
  3. using System.Text.Json.Serialization;
  4. using System.Text.Json.Serialization.Metadata;
  5. namespace Terminal.Gui.ConfigurationTests;
  6. public class SerializableConfigurationPropertyTests
  7. {
  8. /// <summary>
  9. /// If this test fails, you need to add a new property to <see cref="SourceGenerationContext"/> to support serialization of the new property type.
  10. /// </summary>
  11. [Fact]
  12. public void Test_SerializableConfigurationProperty_Types_Added_To_JsonSerializerContext ()
  13. {
  14. // The assembly containing the types to inspect
  15. var assembly = Assembly.GetAssembly (typeof (SourceGenerationContext));
  16. // Get all types from the assembly
  17. var types = assembly!.GetTypes ();
  18. // Find all properties with the SerializableConfigurationProperty attribute
  19. var properties = new List<PropertyInfo> ();
  20. foreach (var type in types)
  21. {
  22. properties.AddRange (type.GetProperties ().Where (p =>
  23. p.GetCustomAttributes (typeof (SerializableConfigurationProperty), false).Any ()));
  24. }
  25. // Get the types of the properties
  26. var propertyTypes = properties.Select (p => p.PropertyType).Distinct ();
  27. // Get the types registered in the JsonSerializerContext derived class
  28. var contextType = typeof (SourceGenerationContext);
  29. var contextTypes = GetRegisteredTypes (contextType);
  30. // Ensure all property types are included in the JsonSerializerContext derived class
  31. IEnumerable<Type> collection = contextTypes as Type [] ?? contextTypes.ToArray ();
  32. foreach (var type in propertyTypes)
  33. {
  34. Assert.Contains (type, collection);
  35. }
  36. // Ensure no property has the generic JsonStringEnumConverter<>
  37. EnsureNoSpecifiedConverters (properties, new [] { typeof (JsonStringEnumConverter<>) });
  38. // Ensure no property has the type RuneJsonConverter
  39. EnsureNoSpecifiedConverters (properties, new [] { typeof (RuneJsonConverter) });
  40. // Ensure no property has the type KeyJsonConverter
  41. EnsureNoSpecifiedConverters (properties, new [] { typeof (KeyJsonConverter) });
  42. // Find all classes with the JsonConverter attribute of type ScopeJsonConverter<>
  43. var classesWithScopeJsonConverter = types.Where (t =>
  44. t.GetCustomAttributes (typeof (JsonConverterAttribute), false)
  45. .Any (attr => ((JsonConverterAttribute)attr).ConverterType!.IsGenericType &&
  46. ((JsonConverterAttribute)attr).ConverterType!.GetGenericTypeDefinition () == typeof (ScopeJsonConverter<>)));
  47. // Ensure all these classes are included in the JsonSerializerContext derived class
  48. foreach (var type in classesWithScopeJsonConverter)
  49. {
  50. Assert.Contains (type, collection);
  51. }
  52. }
  53. private static IEnumerable<Type> GetRegisteredTypes (Type contextType)
  54. {
  55. // Use reflection to find which types are registered in the JsonSerializerContext
  56. var registeredTypes = new List<Type> ();
  57. var properties = contextType.GetProperties (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
  58. foreach (var property in properties)
  59. {
  60. if (property.PropertyType.IsGenericType &&
  61. property.PropertyType.GetGenericTypeDefinition () == typeof (JsonTypeInfo<>))
  62. {
  63. registeredTypes.Add (property.PropertyType.GetGenericArguments () [0]);
  64. }
  65. }
  66. return registeredTypes.Distinct ();
  67. }
  68. private static void EnsureNoSpecifiedConverters (List<PropertyInfo> properties, IEnumerable<Type> converterTypes)
  69. {
  70. // Ensure no property has any of the specified converter types
  71. foreach (var property in properties)
  72. {
  73. var jsonConverterAttributes = property.GetCustomAttributes (typeof (JsonConverterAttribute), false)
  74. .Cast<JsonConverterAttribute> ();
  75. foreach (var attribute in jsonConverterAttributes)
  76. {
  77. foreach (var converterType in converterTypes)
  78. {
  79. if (attribute.ConverterType!.IsGenericType &&
  80. attribute.ConverterType.GetGenericTypeDefinition () == converterType)
  81. {
  82. Assert.Fail ($"Property '{property.Name}' should not use the converter '{converterType.Name}'.");
  83. }
  84. if (!attribute.ConverterType!.IsGenericType &&
  85. attribute.ConverterType == converterType)
  86. {
  87. Assert.Fail ($"Property '{property.Name}' should not use the converter '{converterType.Name}'.");
  88. }
  89. }
  90. }
  91. }
  92. }
  93. }