NodeSystemTests.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using System.Collections.Immutable;
  2. using System.Reflection;
  3. using ChunkyImageLib;
  4. using ChunkyImageLib.DataHolders;
  5. using PixiEditor.AvaloniaUI.Helpers;
  6. using PixiEditor.AvaloniaUI.Models.Serialization;
  7. using PixiEditor.AvaloniaUI.Models.Serialization.Factories;
  8. using PixiEditor.ChangeableDocument.Changeables.Animations;
  9. using PixiEditor.ChangeableDocument.Changeables.Graph;
  10. using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
  11. using PixiEditor.ChangeableDocument.Changeables.Interfaces;
  12. using PixiEditor.ChangeableDocument.Changes.NodeGraph;
  13. using PixiEditor.ChangeableDocument.Rendering;
  14. using PixiEditor.DrawingApi.Core.Bridge;
  15. using PixiEditor.DrawingApi.Skia;
  16. using PixiEditor.Numerics;
  17. using PixiEditor.Parser.Skia.Encoders;
  18. using Xunit.Abstractions;
  19. using Xunit.Sdk;
  20. namespace PixiEditor.Backend.Tests;
  21. public class NodeSystemTests
  22. {
  23. private readonly ITestOutputHelper output;
  24. private Type[] knownNonSerializableTypes = new[]
  25. {
  26. typeof(Filter)
  27. };
  28. public NodeSystemTests(ITestOutputHelper output)
  29. {
  30. this.output = output;
  31. if (!DrawingBackendApi.HasBackend)
  32. DrawingBackendApi.SetupBackend(new SkiaDrawingBackend());
  33. }
  34. [Fact]
  35. public void TestThatNodeGraphExecutesEmptyOutputNode()
  36. {
  37. NodeGraph graph = new NodeGraph();
  38. OutputNode outputNode = new OutputNode();
  39. graph.AddNode(outputNode);
  40. using RenderingContext context = new RenderingContext(0, VecI.Zero, ChunkResolution.Full, new VecI(1, 1));
  41. graph.Execute(context);
  42. Assert.Null(outputNode.CachedResult);
  43. }
  44. [Fact]
  45. public void TestThatCreateSimpleNodeDoesntThrow()
  46. {
  47. var allNodeTypes = typeof(Node).Assembly.GetTypes()
  48. .Where(x =>
  49. x.IsAssignableTo(typeof(Node))
  50. && x is { IsAbstract: false, IsInterface: false }
  51. && x.GetCustomAttribute<PairNodeAttribute>() == null).ToList();
  52. IReadOnlyDocument target = new MockDocument();
  53. foreach (var type in allNodeTypes)
  54. {
  55. var node = NodeOperations.CreateNode(type, target);
  56. Assert.NotNull(node);
  57. }
  58. }
  59. [Fact]
  60. public void TestThatCreatePairNodeDoesntThrow()
  61. {
  62. var allNodeTypes = typeof(Node).Assembly.GetTypes()
  63. .Where(x =>
  64. x.IsAssignableTo(typeof(Node))
  65. && x is { IsAbstract: false, IsInterface: false }
  66. && x.GetCustomAttribute<PairNodeAttribute>() != null).ToList();
  67. IReadOnlyDocument target = new MockDocument();
  68. Dictionary<Type, Type> pairs = new();
  69. for (var i = 0; i < allNodeTypes.Count; i++)
  70. {
  71. var type = allNodeTypes[i];
  72. var pairAttribute = type.GetCustomAttribute<PairNodeAttribute>();
  73. if (pairAttribute == null) continue;
  74. if (!pairAttribute.IsStartingType) continue;
  75. pairs[type] = pairAttribute.OtherType;
  76. }
  77. foreach (var type in pairs)
  78. {
  79. var startNode = NodeOperations.CreateNode(type.Key, target);
  80. var endNode = NodeOperations.CreateNode(type.Value, target, startNode);
  81. Assert.NotNull(startNode);
  82. Assert.NotNull(endNode);
  83. }
  84. }
  85. [Fact]
  86. public void TestThatSerializeNodeDoesntThrow()
  87. {
  88. var allNodeTypes = GetNodeTypesWithoutPairs();
  89. IReadOnlyDocument target = new MockDocument();
  90. foreach (var type in allNodeTypes)
  91. {
  92. var node = NodeOperations.CreateNode(type, target);
  93. Assert.NotNull(node);
  94. Dictionary<string, object> data = new Dictionary<string, object>();
  95. node.SerializeAdditionalData(data);
  96. Assert.NotNull(data);
  97. }
  98. }
  99. [Fact]
  100. private void TestThatAllInputsAreSerializableOrHaveFactories()
  101. {
  102. var allNodeTypes = GetNodeTypesWithoutPairs();
  103. var allFoundFactories = typeof(SerializationFactory).Assembly.GetTypes()
  104. .Where(x => x.IsAssignableTo(typeof(SerializationFactory))
  105. && x is { IsAbstract: false, IsInterface: false }).ToList();
  106. List<SerializationFactory> factories = new();
  107. QoiEncoder encoder = new QoiEncoder();
  108. SerializationConfig config = new SerializationConfig(encoder);
  109. foreach (var factoryType in allFoundFactories)
  110. {
  111. var factory = (SerializationFactory)Activator.CreateInstance(factoryType);
  112. factories.Add(factory);
  113. }
  114. IReadOnlyDocument target = new MockDocument();
  115. foreach (var type in allNodeTypes)
  116. {
  117. var node = NodeOperations.CreateNode(type, target);
  118. Assert.NotNull(node);
  119. foreach (var input in node.InputProperties)
  120. {
  121. if (knownNonSerializableTypes.Contains(input.ValueType)) continue;
  122. if (input.ValueType.IsAssignableTo(typeof(Delegate))) continue;
  123. bool hasFactory = factories.Any(x => x.OriginalType == input.ValueType);
  124. Assert.True(
  125. input.ValueType.IsValueType || input.ValueType == typeof(string) || hasFactory,
  126. $"{input.ValueType} doesn't have a factory and is not serializable. Property: {input.InternalPropertyName}, NodeType: {node.GetType().Name}");
  127. }
  128. }
  129. }
  130. private static List<Type> GetNodeTypesWithoutPairs()
  131. {
  132. var allNodeTypes = typeof(Node).Assembly.GetTypes()
  133. .Where(x =>
  134. x.IsAssignableTo(typeof(Node))
  135. && x is { IsAbstract: false, IsInterface: false }
  136. && x.GetCustomAttribute<PairNodeAttribute>() == null).ToList();
  137. return allNodeTypes;
  138. }
  139. }