using UnityEngine;
namespace Unity.Netcode.TestHelpers.Runtime
{
///
/// Can be used independently or assigned to in the
/// event the default timeout period needs to be adjusted
///
public class TimeoutHelper
{
protected const float k_DefaultTimeOutWaitPeriod = 2.0f;
private float m_MaximumTimeBeforeTimeOut;
private float m_TimeOutPeriod;
protected bool m_IsStarted { get; private set; }
public bool TimedOut { get; internal set; }
private float m_TimeStarted;
private float m_TimeStopped;
public float GetTimeElapsed()
{
if (m_IsStarted)
{
return Time.realtimeSinceStartup - m_TimeStarted;
}
else
{
return m_TimeStopped - m_TimeStarted;
}
}
protected virtual void OnStart()
{
}
public void Start()
{
m_TimeStopped = 0.0f;
m_TimeStarted = Time.realtimeSinceStartup;
m_MaximumTimeBeforeTimeOut = Time.realtimeSinceStartup + m_TimeOutPeriod;
m_IsStarted = true;
TimedOut = false;
OnStart();
}
protected virtual void OnStop()
{
}
public void Stop()
{
if (m_TimeStopped == 0.0f)
{
m_TimeStopped = Time.realtimeSinceStartup;
}
TimedOut = HasTimedOut();
m_IsStarted = false;
OnStop();
}
protected virtual bool OnHasTimedOut()
{
return m_IsStarted ? m_MaximumTimeBeforeTimeOut < Time.realtimeSinceStartup : TimedOut;
}
public bool HasTimedOut()
{
return OnHasTimedOut();
}
public TimeoutHelper(float timeOutPeriod = k_DefaultTimeOutWaitPeriod)
{
m_TimeOutPeriod = timeOutPeriod;
}
}
///
/// This can be used in place of TimeoutHelper if you suspect a test is having
/// issues on a system where the frame rate is running slow than expected and
/// allowing a certain number of frame updates is required.
///
public class TimeoutFrameCountHelper : TimeoutHelper
{
private const uint k_DefaultTickRate = 30;
private float m_TotalFramesToWait;
private int m_StartFrameCount;
private int m_EndFrameCount;
private bool m_ReachedFrameCount;
public int GetFrameCount()
{
if (m_IsStarted)
{
return Time.frameCount - m_StartFrameCount;
}
else
{
return m_EndFrameCount - m_StartFrameCount;
}
}
protected override void OnStop()
{
if (m_EndFrameCount == 0)
{
m_EndFrameCount = Time.frameCount;
}
base.OnStop();
}
protected override bool OnHasTimedOut()
{
var currentFrameCountDelta = Time.frameCount - m_StartFrameCount;
if (m_IsStarted)
{
m_ReachedFrameCount = currentFrameCountDelta >= m_TotalFramesToWait;
}
// Only time out if we have both exceeded the time period and the expected number of frames has reached the expected number of frames
// (this handles the scenario where some systems are running a much lower frame rate)
return m_ReachedFrameCount && base.OnHasTimedOut();
}
protected override void OnStart()
{
m_EndFrameCount = 0;
m_StartFrameCount = Time.frameCount;
base.OnStart();
}
public TimeoutFrameCountHelper(float timeOutPeriod = k_DefaultTimeOutWaitPeriod, uint tickRate = k_DefaultTickRate) : base(timeOutPeriod)
{
// Calculate the expected number of frame updates that should occur during the tick count wait period
var frameFrequency = 1.0f / (Application.targetFrameRate >= 60 && Application.targetFrameRate <= 100 ? Application.targetFrameRate : 60.0f);
var tickFrequency = 1.0f / tickRate;
var framesPerTick = tickFrequency / frameFrequency;
var totalExpectedTicks = timeOutPeriod / tickFrequency;
m_TotalFramesToWait = framesPerTick * totalExpectedTicks;
}
}
}