NodeSystemTests.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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) ||
  114. hasFactory,
  115. $"{input.ValueType} doesn't have a factory and is not serializable. Property: {input.InternalPropertyName}, NodeType: {node.GetType().Name}");
  116. }
  117. }
  118. }
  119. [Fact]
  120. public void TestThatAllVectorDataTypesHaveSerializationFactories()
  121. {
  122. var allVectorTypes = typeof(ShapeVectorData).Assembly.GetTypes()
  123. .Where(x => x.IsAssignableTo(typeof(ShapeVectorData))
  124. && x is { IsAbstract: false, IsInterface: false }).ToList();
  125. QoiEncoder encoder = new QoiEncoder();
  126. SerializationConfig config = new SerializationConfig(encoder, ColorSpace.CreateSrgbLinear());
  127. var factoryTypes = typeof(SerializationFactory).Assembly.GetTypes()
  128. .Where(x => x.IsAssignableTo(typeof(SerializationFactory))
  129. && x is { IsAbstract: false, IsInterface: false }).ToList();
  130. List<SerializationFactory> factories = new();
  131. foreach (var factoryType in factoryTypes)
  132. {
  133. var factory = (SerializationFactory)Activator.CreateInstance(factoryType);
  134. factories.Add(factory);
  135. }
  136. foreach (var type in allVectorTypes)
  137. {
  138. bool hasFactory = factories.Any(x => x.OriginalType == type);
  139. Assert.True(hasFactory, $"{type} doesn't have a factory.");
  140. }
  141. }
  142. [Fact]
  143. public void TestThatSerializationFactoriesIdsAreNotDuplicated()
  144. {
  145. var factoryTypes = typeof(SerializationFactory).Assembly.GetTypes()
  146. .Where(x => x.IsAssignableTo(typeof(SerializationFactory))
  147. && x is { IsAbstract: false, IsInterface: false }).ToList();
  148. List<SerializationFactory> factories = new();
  149. foreach (var factoryType in factoryTypes)
  150. {
  151. var factory = (SerializationFactory)Activator.CreateInstance(factoryType);
  152. factories.Add(factory);
  153. }
  154. List<string> ids = new();
  155. foreach (var factory in factories)
  156. {
  157. Assert.DoesNotContain(factory.DeserializationId, ids);
  158. ids.Add(factory.DeserializationId);
  159. }
  160. }
  161. private static List<Type> GetNodeTypesWithoutPairs()
  162. {
  163. var allNodeTypes = typeof(Node).Assembly.GetTypes()
  164. .Where(x =>
  165. x.IsAssignableTo(typeof(Node))
  166. && x is { IsAbstract: false, IsInterface: false }
  167. && x.GetCustomAttribute<PairNodeAttribute>() == null).ToList();
  168. return allNodeTypes;
  169. }
  170. }