AllocatingGCMemoryConstraint.cs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. using System;
  2. using NUnit.Framework;
  3. using NUnit.Framework.Constraints;
  4. using UnityEngine.Profiling;
  5. namespace UnityEngine.TestTools.Constraints
  6. {
  7. public class AllocatingGCMemoryConstraint : Constraint
  8. {
  9. private class AllocatingGCMemoryResult : ConstraintResult
  10. {
  11. private readonly int diff;
  12. public AllocatingGCMemoryResult(IConstraint constraint, object actualValue, int diff) : base(constraint, actualValue, diff > 0)
  13. {
  14. this.diff = diff;
  15. }
  16. public override void WriteMessageTo(MessageWriter writer)
  17. {
  18. if (diff == 0)
  19. writer.WriteMessageLine("The provided delegate did not make any GC allocations.");
  20. else
  21. writer.WriteMessageLine("The provided delegate made {0} GC allocation(s).", diff);
  22. }
  23. }
  24. private ConstraintResult ApplyTo(Action action, object original)
  25. {
  26. var recorder = Recorder.Get("GC.Alloc");
  27. // The recorder was created enabled, which means it captured the creation of the Recorder object itself, etc.
  28. // Disabling it flushes its data, so that we can retrieve the sample block count and have it correctly account
  29. // for these initial allocations.
  30. recorder.enabled = false;
  31. #if !UNITY_WEBGL
  32. recorder.FilterToCurrentThread();
  33. #endif
  34. recorder.enabled = true;
  35. try
  36. {
  37. action();
  38. }
  39. finally
  40. {
  41. recorder.enabled = false;
  42. #if !UNITY_WEBGL
  43. recorder.CollectFromAllThreads();
  44. #endif
  45. }
  46. return new AllocatingGCMemoryResult(this, original, recorder.sampleBlockCount);
  47. }
  48. public override ConstraintResult ApplyTo(object obj)
  49. {
  50. if (obj == null)
  51. throw new ArgumentNullException();
  52. TestDelegate d = obj as TestDelegate;
  53. if (d == null)
  54. throw new ArgumentException(string.Format("The actual value must be a TestDelegate but was {0}",
  55. obj.GetType()));
  56. return ApplyTo(() => d.Invoke(), obj);
  57. }
  58. public override ConstraintResult ApplyTo<TActual>(ActualValueDelegate<TActual> del)
  59. {
  60. if (del == null)
  61. throw new ArgumentNullException();
  62. return ApplyTo(() => del.Invoke(), del);
  63. }
  64. public override string Description
  65. {
  66. get { return "allocates GC memory"; }
  67. }
  68. }
  69. }