262 lines
9.4 KiB
C#

#if TEST_FRAMEWORK_INSTALLED
using System.Collections;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using NUnit.Framework;
using PrimeTween;
using UnityEngine;
using UnityEngine.TestTools;
using Assert = NUnit.Framework.Assert;
using Object = UnityEngine.Object;
public partial class Tests {
Transform transform;
static TweenSettings<Vector3> settingsVector3 => new TweenSettings<Vector3>(Vector3.zero, Vector3.one, getDt() * 2f);
static bool setTweenCapacityBeforeSplashScreenLoggedError;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
static void beforeSplashScreen() {
Application.logMessageReceived += OnLogMessageReceived;
PrimeTweenConfig.SetTweensCapacity(capacityForTest);
Application.logMessageReceived -= OnLogMessageReceived;
static void OnLogMessageReceived(string condition, string stacktrace, LogType type) => setTweenCapacityBeforeSplashScreenLoggedError = true;
}
[OneTimeSetUp]
public void oneTimeSetup() {
Assert.IsFalse(setTweenCapacityBeforeSplashScreenLoggedError, "setTweenCapacityBeforeSplashScreenLoggedError");
transform = new GameObject().transform;
PrimeTweenConfig.SetTweensCapacity(capacityForTest);
}
const int targetFrameRate = -1;
[SetUp]
public void setUp() => Application.targetFrameRate = targetFrameRate;
static int tweensCount => PrimeTweenManager.Instance.tweensCount;
[Test]
public void CreatingTweenWithDestroyedTargetReturnsTweenToPool() {
if (tweensCount != 0) {
Tween.StopAll();
}
Assert.AreEqual(0, tweensCount);
var target = new GameObject();
var targetTr = target.transform;
Object.DestroyImmediate(target);
var pool = PrimeTweenManager.Instance.pool;
var poolCount = pool.Count;
{
expectTargetIsNull();
var t = Tween.Delay(target, 0.0001f);
Assert.IsFalse(t.isAlive);
Assert.AreEqual(poolCount, pool.Count);
}
{
expectTargetIsNull();
var t = Tween.Custom(target, 0, 0, 1, delegate { });
Assert.IsFalse(t.isAlive);
Assert.AreEqual(poolCount, pool.Count);
}
{
expectTargetIsNull();
Assert.IsTrue(targetTr == null);
var t = Tween.Position(targetTr, default, 1);
Assert.IsFalse(t.isAlive);
Assert.AreEqual(poolCount, pool.Count);
}
Assert.AreEqual(0, tweensCount);
}
[UnityTest]
public IEnumerator TweenTargetDestroyedInSequenceWithCallbacks() {
expectOnCompleteIgnored();
var target = new GameObject("t1");
var duration = getDt();
yield return Sequence.Create()
.Group(Tween.Custom(target, 0, 1, duration, delegate { }))
.Chain(Tween.Custom(target, 0, 1, duration, (_target, _) => Object.DestroyImmediate(_target)).OnComplete(() => {}))
.Chain(Tween.Delay(target, duration))
.ToYieldInstruction();
yield return null;
Assert.AreEqual(0, tweensCount, "TweenCoroutineEnumerator should not check the target's destruction.");
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator TweenTargetDestroyedInSequence() {
var target = new GameObject("t1");
const float duration = 0.03f;
yield return Sequence.Create()
.Group(Tween.Custom(target, 0, 1, duration, delegate { }))
.Chain(Tween.Custom(target, 0, 1, duration, (_target, _) => Object.DestroyImmediate(_target)))
.Chain(Tween.Delay(target, duration))
.ToYieldInstruction();
LogAssert.NoUnexpectedReceived();
}
[Test]
public void SequenceTargetDestroyedBeforeCallingStop() {
var tweener = createTweenAndDestroyTargetImmediately(false);
Sequence.Create(tweener).Stop();
}
[Test]
public void SequenceTargetDestroyedBeforeCallingComplete() {
var tweener = createTweenAndDestroyTargetImmediately().OnComplete(Assert.Fail);
Sequence.Create(tweener).Complete();
}
[UnityTest]
public IEnumerator TargetDestroyedBeforeCallingCompleteAll() {
createTweenAndDestroyTargetImmediately().OnComplete(Assert.Fail);
Tween.CompleteAll();
Tween.SetPausedAll(true);
Tween.SetPausedAll(false);
Assert.AreEqual(0, getCurrentTweensCount());
yield break;
}
static int getCurrentTweensCount() => tweensCount;
[UnityTest]
public IEnumerator TargetDestroyedBeforeCallingCompleteByTarget() {
var tweener = createTweenAndDestroyTargetImmediately().OnComplete(Assert.Fail);
Assert.AreEqual(Tween.CompleteAll(tweener.tween.target), 1);
Tween.SetPausedAll(true);
Tween.SetPausedAll(false);
Assert.AreEqual(1, getCurrentTweensCount());
yield return tweener;
Assert.AreEqual(0, tweensCount);
}
[Test]
public void TargetDestroyedBeforeCallingComplete() {
createTweenAndDestroyTargetImmediately().OnComplete(Assert.Fail).Complete();
}
[UnityTest]
public IEnumerator TargetDestroyedBeforeAddingOnComplete1() {
yield return createTweenAndDestroyTargetImmediately()
.OnComplete(delegate { })
.ToYieldInstruction();
}
[UnityTest]
public IEnumerator TargetDestroyedBeforeAddingOnComplete2() {
yield return createTweenAndDestroyTargetImmediately()
.OnComplete(this, delegate { })
.ToYieldInstruction();
}
[UnityTest]
public IEnumerator TargetDestroyedSetIsPaused() {
var t = createTweenAndDestroyTargetImmediately().OnComplete(Assert.Fail);
t.isPaused = true; // changing isPaused is ok
t.isPaused = false;
yield return t.ToYieldInstruction();
}
static Tween createTweenAndDestroyTargetImmediately(bool expectOnCompleteIgnoredWarning = true) {
if (expectOnCompleteIgnoredWarning) {
expectOnCompleteIgnored();
}
var tempTransform = new GameObject().transform;
var tweener = Tween.LocalPosition(tempTransform, settingsVector3);
Object.DestroyImmediate(tempTransform.gameObject);
Assert.IsTrue(tweener.isAlive);
return tweener;
}
[UnityTest]
public IEnumerator OnCompleteIsNotCalledIfTargetDestroyed() {
expectOnCompleteIgnored();
var tempTransform = new GameObject().transform;
var tweener = Tween.LocalPosition(tempTransform, settingsVector3).OnComplete(Assert.Fail);
Object.DestroyImmediate(tempTransform.gameObject);
while (tweener.isAlive) {
yield return null;
}
}
[UnityTest]
public IEnumerator SettingCyclesOnDestroyedTween() {
var t = createTweenAndDestroyTargetImmediately().OnComplete(Assert.Fail);
t.SetRemainingCycles(2);
yield return t;
}
[Test]
public void IgnoreIfOnCompleteTargetDestroyed() {
{
var target = new GameObject(nameof(IgnoreIfOnCompleteTargetDestroyed));
var t = Tween.Delay(1f).OnComplete(target, _ => Assert.Fail());
Object.DestroyImmediate(target);
expectOnCompleteIgnored();
t.Complete();
}
{
var target = new GameObject(nameof(IgnoreIfOnCompleteTargetDestroyed));
var t = Tween.Delay(1f).OnComplete(target, _ => Assert.Fail(), false);
Object.DestroyImmediate(target);
t.Complete();
}
LogAssert.NoUnexpectedReceived();
}
[Test]
public async Task TargetDestructionAsync() {
{
expectOnCompleteIgnored();
var target = new GameObject(nameof(TargetDestructionAsync));
await Tween.Custom(target, 0, 1, 1, delegate { Object.DestroyImmediate(target); })
.OnComplete(Assert.Fail);
}
{
var target = new GameObject(nameof(TargetDestructionAsync));
await Tween.Custom(target, 0, 1, 1, delegate { Object.DestroyImmediate(target); })
.OnComplete(Assert.Fail, false);
}
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator TargetDestructionInCoroutine() {
if (tweensCount > 0) {
Tween.StopAll();
}
Assert.AreEqual(0, tweensCount);
{
PrimeTweenConfig.warnStructBoxingAllocationInCoroutine = true;
expectCoroutineBoxingWarning();
expectOnCompleteIgnored();
var target = new GameObject(nameof(TargetDestructionInCoroutine));
yield return Tween.Custom(target, 0, 1, 1, delegate {
Object.DestroyImmediate(target);
}).OnComplete(Assert.Fail);
}
{
var target = new GameObject(nameof(TargetDestructionInCoroutine));
yield return Tween.Custom(target, 0, 1, 1, delegate {
Object.DestroyImmediate(target);
}).OnComplete(Assert.Fail, false)
.ToYieldInstruction();
}
LogAssert.NoUnexpectedReceived();
}
[UnityTest]
public IEnumerator TargetDestructionWhilePaused() {
var target = new GameObject(nameof(TargetDestructionWhilePaused));
var tween = Tween.Delay(target, 0.05f);
tween.isPaused = true;
Object.DestroyImmediate(target);
yield return null;
Assert.IsFalse(tween.isAlive);
}
}
#endif