NodeSystemTests.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. using System.Reflection;
  2. using Drawie.Backend.Core.Bridge;
  3. using Drawie.Backend.Core.Surfaces.ImageData;
  4. using Drawie.Interop.Avalonia.Core;
  5. using Drawie.Interop.VulkanAvalonia;
  6. using Drawie.Skia;
  7. using PixiEditor.ChangeableDocument.Changeables.Graph;
  8. using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
  9. using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
  10. using PixiEditor.ChangeableDocument.Changeables.Interfaces;
  11. using PixiEditor.ChangeableDocument.Changes.NodeGraph;
  12. using PixiEditor.Models.Serialization;
  13. using PixiEditor.Models.Serialization.Factories;
  14. using PixiEditor.Parser.Skia.Encoders;
  15. using Xunit.Abstractions;
  16. namespace PixiEditor.Backend.Tests;
  17. public class NodeSystemTests
  18. {
  19. private readonly ITestOutputHelper output;
  20. private Type[] knownNonSerializableTypes = new[]
  21. {
  22. typeof(Filter),
  23. typeof(Painter)
  24. };
  25. public NodeSystemTests(ITestOutputHelper output)
  26. {
  27. this.output = output;
  28. if (!DrawingBackendApi.HasBackend)
  29. DrawingBackendApi.SetupBackend(new SkiaDrawingBackend(), new AvaloniaRenderingDispatcher());
  30. }
  31. [Fact]
  32. public void TestThatCreateSimpleNodeDoesntThrow()
  33. {
  34. var allNodeTypes = typeof(Node).Assembly.GetTypes()
  35. .Where(x =>
  36. x.IsAssignableTo(typeof(Node))
  37. && x is { IsAbstract: false, IsInterface: false }
  38. && x.GetCustomAttribute<PairNodeAttribute>() == null).ToList();
  39. IReadOnlyDocument target = new MockDocument();
  40. foreach (var type in allNodeTypes)
  41. {
  42. var node = NodeOperations.CreateNode(type, target);
  43. Assert.NotNull(node);
  44. }
  45. }
  46. [Fact]
  47. public void TestThatCreatePairNodeDoesntThrow()
  48. {
  49. var allNodeTypes = typeof(Node).Assembly.GetTypes()
  50. .Where(x =>
  51. x.IsAssignableTo(typeof(Node))
  52. && x is { IsAbstract: false, IsInterface: false }
  53. && x.GetCustomAttribute<PairNodeAttribute>() != null).ToList();
  54. IReadOnlyDocument target = new MockDocument();
  55. Dictionary<Type, Type> pairs = new();
  56. for (var i = 0; i < allNodeTypes.Count; i++)
  57. {
  58. var type = allNodeTypes[i];
  59. var pairAttribute = type.GetCustomAttribute<PairNodeAttribute>();
  60. if (pairAttribute == null) continue;
  61. if (!pairAttribute.IsStartingType) continue;
  62. pairs[type] = pairAttribute.OtherType;
  63. }
  64. foreach (var type in pairs)
  65. {
  66. var startNode = NodeOperations.CreateNode(type.Key, target);
  67. var endNode = NodeOperations.CreateNode(type.Value, target);
  68. Assert.NotNull(startNode);
  69. Assert.NotNull(endNode);
  70. }
  71. }
  72. [Fact]
  73. public void TestThatSerializeNodeDoesntThrow()
  74. {
  75. var allNodeTypes = GetNodeTypesWithoutPairs();
  76. IReadOnlyDocument target = new MockDocument();
  77. foreach (var type in allNodeTypes)
  78. {
  79. var node = NodeOperations.CreateNode(type, target);
  80. Assert.NotNull(node);
  81. Dictionary<string, object> data = new Dictionary<string, object>();
  82. node.SerializeAdditionalData(data);
  83. Assert.NotNull(data);
  84. }
  85. }
  86. [Fact]
  87. private void TestThatAllInputsAreSerializableOrHaveFactories()
  88. {
  89. var allNodeTypes = GetNodeTypesWithoutPairs();
  90. var allFoundFactories = typeof(SerializationFactory).Assembly.GetTypes()
  91. .Where(x => x.IsAssignableTo(typeof(SerializationFactory))
  92. && x is { IsAbstract: false, IsInterface: false }).ToList();
  93. List<SerializationFactory> factories = new();
  94. QoiEncoder encoder = new QoiEncoder();
  95. SerializationConfig config = new SerializationConfig(encoder, ColorSpace.CreateSrgbLinear());
  96. foreach (var factoryType in allFoundFactories)
  97. {
  98. var factory = (SerializationFactory)Activator.CreateInstance(factoryType);
  99. factories.Add(factory);
  100. }
  101. IReadOnlyDocument target = new MockDocument();
  102. foreach (var type in allNodeTypes)
  103. {
  104. var node = NodeOperations.CreateNode(type, target);
  105. Assert.NotNull(node);
  106. foreach (var input in node.InputProperties)
  107. {
  108. if (knownNonSerializableTypes.Contains(input.ValueType)) continue;
  109. if (input.ValueType.IsAbstract) continue;
  110. if (input.ValueType.IsAssignableTo(typeof(Delegate))) continue;
  111. bool hasFactory = factories.Any(x => x.OriginalType == input.ValueType);
  112. Assert.True(
  113. input.ValueType.IsPrimitive || input.ValueType.IsEnum || input.ValueType == typeof(string) || hasFactory,
  114. $"{input.ValueType} doesn't have a factory and is not serializable. Property: {input.InternalPropertyName}, NodeType: {node.GetType().Name}");
  115. }
  116. }
  117. }
  118. [Fact]
  119. public void TestThatAllVectorDataTypesHaveSerializationFactories()
  120. {
  121. var allVectorTypes = typeof(ShapeVectorData).Assembly.GetTypes()
  122. .Where(x => x.IsAssignableTo(typeof(ShapeVectorData))
  123. && x is { IsAbstract: false, IsInterface: false }).ToList();
  124. QoiEncoder encoder = new QoiEncoder();
  125. SerializationConfig config = new SerializationConfig(encoder, ColorSpace.CreateSrgbLinear());
  126. var factoryTypes = typeof(SerializationFactory).Assembly.GetTypes()
  127. .Where(x => x.IsAssignableTo(typeof(SerializationFactory))
  128. && x is { IsAbstract: false, IsInterface: false }).ToList();
  129. List<SerializationFactory> factories = new();
  130. foreach (var factoryType in factoryTypes)
  131. {
  132. var factory = (SerializationFactory)Activator.CreateInstance(factoryType);
  133. factories.Add(factory);
  134. }
  135. foreach (var type in allVectorTypes)
  136. {
  137. bool hasFactory = factories.Any(x => x.OriginalType == type);
  138. Assert.True(hasFactory, $"{type} doesn't have a factory.");
  139. }
  140. }
  141. [Fact]
  142. public void TestThatSerializationFactoriesIdsAreNotDuplicated()
  143. {
  144. var factoryTypes = typeof(SerializationFactory).Assembly.GetTypes()
  145. .Where(x => x.IsAssignableTo(typeof(SerializationFactory))
  146. && x is { IsAbstract: false, IsInterface: false }).ToList();
  147. List<SerializationFactory> factories = new();
  148. foreach (var factoryType in factoryTypes)
  149. {
  150. var factory = (SerializationFactory)Activator.CreateInstance(factoryType);
  151. factories.Add(factory);
  152. }
  153. List<string> ids = new();
  154. foreach (var factory in factories)
  155. {
  156. Assert.DoesNotContain(factory.DeserializationId, ids);
  157. ids.Add(factory.DeserializationId);
  158. }
  159. }
  160. private static List<Type> GetNodeTypesWithoutPairs()
  161. {
  162. var allNodeTypes = typeof(Node).Assembly.GetTypes()
  163. .Where(x =>
  164. x.IsAssignableTo(typeof(Node))
  165. && x is { IsAbstract: false, IsInterface: false }
  166. && x.GetCustomAttribute<PairNodeAttribute>() == null).ToList();
  167. return allNodeTypes;
  168. }
  169. }