SerializableConfigurationPropertyTests.cs 4.6 KB

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