#if MULTIPLAYER_TOOLS using System.Collections; using System.Linq; using NUnit.Framework; using Unity.Multiplayer.Tools.MetricTypes; using Unity.Multiplayer.Tools.NetStats; namespace Unity.Netcode.TestHelpers.Runtime.Metrics { internal abstract class WaitForMetricValues : IMetricObserver { protected readonly string m_MetricName; protected bool m_Found; protected bool m_HasError; protected string m_Error; protected uint m_NbFrames = 0; public WaitForMetricValues(IMetricDispatcher dispatcher, DirectionalMetricInfo directionalMetricName) { m_MetricName = directionalMetricName.Id; dispatcher.RegisterObserver(this); } abstract public void Observe(MetricCollection collection); public void AssertMetricValuesHaveNotBeenFound() { if (m_HasError) { Assert.Fail(m_Error); } if (!m_Found) { Assert.Pass(); } else { Assert.Fail(); } } public IEnumerator WaitForMetricsReceived() { yield return WaitForFrames(60); } protected void AssertHasError() { if (m_HasError) { Assert.Fail(m_Error); } } protected void AssertIsFound() { if (!m_Found) { Assert.Fail($"Found no matching values for metric of type '{typeof(TMetric).Name}', with name '{m_MetricName}' during '{m_NbFrames}' frames."); } } protected bool FindMetric(MetricCollection collection, out IMetric metric) { if (m_Found || m_HasError) { metric = null; return false; } metric = collection.Metrics.SingleOrDefault(x => x.Name == m_MetricName); if (metric == default) { m_HasError = true; m_Error = $"Metric collection does not contain metric named '{m_MetricName}'."; return false; } return true; } protected void SetError(IMetric metric) { m_HasError = true; m_Error = $"Metric collection contains a metric of type '{metric.GetType().Name}' for name '{m_MetricName}', but was expecting '{typeof(TMetric).Name}'."; } private IEnumerator WaitForFrames(uint maxNbFrames) { while (!m_Found && m_NbFrames < maxNbFrames) { m_NbFrames++; yield return null; } } } } #endif