Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Sentry.Unity/Integrations/IApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal interface IApplication
string Version { get; }
string PersistentDataPath { get; }
bool IsMainThread { get; }
RuntimePlatform Platform { get; }
}

internal sealed class ApplicationAdapter : IApplication
Expand Down Expand Up @@ -43,6 +44,8 @@ private ApplicationAdapter()

public bool IsMainThread => Thread.CurrentThread.ManagedThreadId == 1;

public RuntimePlatform Platform => Application.platform;

private void OnLogMessageReceived(string condition, string stackTrace, LogType type)
=> LogMessageReceived?.Invoke(condition, stackTrace, type);

Expand Down
4 changes: 2 additions & 2 deletions src/Sentry.Unity/Integrations/SessionIntegration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public void Register(IHub hub, SentryOptions options)
options.DiagnosticLogger?.LogDebug("Registering Session integration.");

// HideFlags.HideAndDontSave hides the GameObject in the hierarchy and prevents changing of scenes from destroying it
var gameListenerObject = new GameObject("SentryListener") {hideFlags = HideFlags.HideAndDontSave};
var gameListener = gameListenerObject.AddComponent<ApplicationPauseListener>();
var gameListenerObject = new GameObject("SentryMonoBehaviour") {hideFlags = HideFlags.HideAndDontSave};
var gameListener = gameListenerObject.AddComponent<SentryMonoBehaviour>();
gameListener.ApplicationResuming += () =>
{
options.DiagnosticLogger?.LogDebug("Resuming session.");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Sentry.Unity.Integrations;
using UnityEngine;

namespace Sentry.Unity
Expand All @@ -7,7 +8,7 @@ namespace Sentry.Unity
/// A MonoBehavior used to forward application focus events to subscribers.
/// </summary>
[DefaultExecutionOrder(-900)]
internal class ApplicationPauseListener : MonoBehaviour
internal class SentryMonoBehaviour : MonoBehaviour
{
/// <summary>
/// Hook to receive an event when the application gains focus.
Expand All @@ -28,6 +29,17 @@ internal class ApplicationPauseListener : MonoBehaviour
// Keeping internal track of running state because OnApplicationPause and OnApplicationFocus get called during startup and would fire false resume events
private bool _isRunning = true;

private IApplication? _application;
internal IApplication Application
{
get
{
_application ??= ApplicationAdapter.Instance;
return _application;
}
set => _application = value;
}

/// <summary>
/// To receive Leaving/Resuming events on Android.
/// <remarks>
Expand All @@ -37,9 +49,9 @@ internal class ApplicationPauseListener : MonoBehaviour
/// </remarks>
/// <seealso href="https://docs.unity3d.com/2019.4/Documentation/ScriptReference/MonoBehaviour.OnApplicationPause.html"/>
/// </summary>
private void OnApplicationPause(bool pauseStatus)
internal void OnApplicationPause(bool pauseStatus)
{
if (Application.platform != RuntimePlatform.Android)
if (Application.Platform != RuntimePlatform.Android)
{
return;
}
Expand All @@ -60,10 +72,10 @@ private void OnApplicationPause(bool pauseStatus)
/// To receive Leaving/Resuming events on all platforms except Android.
/// </summary>
/// <param name="hasFocus"></param>
private void OnApplicationFocus(bool hasFocus)
internal void OnApplicationFocus(bool hasFocus)
{
// To avoid event duplication on Android since the pause event will be handled via OnApplicationPause
if (Application.platform == RuntimePlatform.Android)
if (Application.Platform == RuntimePlatform.Android)
{
return;
}
Expand Down
1 change: 0 additions & 1 deletion src/Sentry.Unity/SentryOptionsUtility.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using Sentry.Unity.Integrations;

namespace Sentry.Unity
Expand Down
5 changes: 3 additions & 2 deletions test/Sentry.Unity.Tests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public IEnumerator Init_OptionsAreDefaulted()
UnitySentryOptionsTests.AssertOptions(expectedOptions, actualOptions!);
}

private static IEnumerator SetupSceneCoroutine(string sceneName)
internal static IEnumerator SetupSceneCoroutine(string sceneName)
{
// load scene with initialized Sentry, SceneManager.LoadSceneAsync(sceneName);
SceneManager.LoadScene(sceneName);
Expand All @@ -244,11 +244,12 @@ private static IEnumerator SetupSceneCoroutine(string sceneName)
LogAssert.ignoreFailingMessages = true;
}

private static IDisposable InitSentrySdk(Action<SentryUnityOptions> configure)
internal static IDisposable InitSentrySdk(Action<SentryUnityOptions> configure)
{
SentryUnity.Init(options =>
{
options.Dsn = "https://94677106febe46b88b9b9ae5efd18a00@o447951.ingest.sentry.io/5439417";

configure.Invoke(options);
});
return new SentryDisposable();
Expand Down
151 changes: 151 additions & 0 deletions test/Sentry.Unity.Tests/SentryMonoBehaviourTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using NUnit.Framework;
using Sentry.Unity.Tests.Stubs;
using UnityEngine;

namespace Sentry.Unity.Tests
{
public class SentryMonoBehaviourTests
{
private class Fixture
{
public SentryMonoBehaviour GetSut(RuntimePlatform platform)
{
var gameObject = new GameObject("PauseTest");
var sentryMonoBehaviour = gameObject.AddComponent<SentryMonoBehaviour>();
sentryMonoBehaviour.Application = new TestApplication(platform: platform);

return sentryMonoBehaviour;
}
}

private Fixture _fixture = null!;

[SetUp]
public void SetUp()
{
_fixture = new Fixture();
}
Comment on lines +24 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void SetUp()
{
_fixture = new Fixture();
}
public void SetUp() => _fixture = new Fixture();


[Test]
public void OnApplicationPause_OnAndroid_ApplicationPausingTriggered()
{
var wasPausingCalled = false;

var sut = _fixture.GetSut(RuntimePlatform.Android);
sut.ApplicationPausing += () => wasPausingCalled = true;

sut.OnApplicationPause(true);

Assert.IsTrue(wasPausingCalled);
}

[Test]
public void OnApplicationPause_NotOnAndroid_ApplicationPausingNotTriggered()
{
var wasPausingCalled = false;

var sut = _fixture.GetSut(RuntimePlatform.IPhonePlayer);
sut.ApplicationPausing += () => wasPausingCalled = true;

sut.OnApplicationPause(true);

Assert.IsFalse(wasPausingCalled);
}

[Test]
public void OnApplicationPause_OnAndroid_ApplicationPausingTriggeredOnlyOnce()
{
var pauseEventTriggerCounter = 0;

var sut = _fixture.GetSut(RuntimePlatform.Android);
sut.ApplicationPausing += () => pauseEventTriggerCounter++;

sut.OnApplicationPause(true);
sut.OnApplicationPause(true);

Assert.AreEqual(1, pauseEventTriggerCounter);
}

[Test]
public void OnApplicationPause_OnAndroid_PausingIsRequiredBeforeApplicationResumingTrigger()
{
var wasPausingCalled = false;
var wasResumingCalled = false;

var sut = _fixture.GetSut(RuntimePlatform.Android);
sut.ApplicationPausing += () => wasPausingCalled = true;
sut.ApplicationResuming += () => wasResumingCalled = true;

sut.OnApplicationPause(false);

Assert.IsFalse(wasResumingCalled);

sut.OnApplicationPause(true);
sut.OnApplicationPause(false);

Assert.IsTrue(wasPausingCalled);
Assert.IsTrue(wasResumingCalled);
}

[Test]
public void OnApplicationFocus_OnAndroid_ApplicationPausingNotTriggered()
{
var wasPausingCalled = false;

var sut = _fixture.GetSut(RuntimePlatform.Android);
sut.ApplicationPausing += () => wasPausingCalled = true;

sut.OnApplicationFocus(false);

Assert.IsFalse(wasPausingCalled);
}

[Test]
public void OnApplicationFocus_NotOnAndroid_ApplicationPausingTriggered()
{
var wasPausingCalled = false;

var sut = _fixture.GetSut(RuntimePlatform.IPhonePlayer);
sut.ApplicationPausing += () => wasPausingCalled = true;

sut.OnApplicationFocus(false);

Assert.IsTrue(wasPausingCalled);
}

[Test]
public void OnApplicationFocus_NotOnAndroid_ApplicationPausingTriggeredOnlyOnce()
{
var pauseEventTriggerCounter = 0;

var sut = _fixture.GetSut(RuntimePlatform.IPhonePlayer);
sut.ApplicationPausing += () => pauseEventTriggerCounter++;

sut.OnApplicationFocus(false);
sut.OnApplicationFocus(false);

Assert.AreEqual(1, pauseEventTriggerCounter);
}

[Test]
public void OnApplicationFocus_NotOnAndroid_PausingIsRequiredBeforeApplicationResumingTrigger()
{
var wasPausingCalled = false;
var wasResumingCalled = false;

var sut = _fixture.GetSut(RuntimePlatform.IPhonePlayer);
sut.ApplicationPausing += () => wasPausingCalled = true;
sut.ApplicationResuming += () => wasResumingCalled = true;

sut.OnApplicationFocus(true);

Assert.IsFalse(wasResumingCalled);

sut.OnApplicationFocus(false);
sut.OnApplicationFocus(true);

Assert.IsTrue(wasPausingCalled);
Assert.IsTrue(wasResumingCalled);
}
}
}
27 changes: 27 additions & 0 deletions test/Sentry.Unity.Tests/SessionIntegrationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;

namespace Sentry.Unity.Tests
{
public class SessionIntegrationTests
{
[UnityTest]
public IEnumerator SessionIntegration_Init_SentryMonoBehaviourCreated()
{
yield return null;

using var _ = IntegrationTests.InitSentrySdk(o =>
{
// o.AutoSessionTracking = true; We expect this to be true by default
});

var sentryGameObject = GameObject.Find("SentryMonoBehaviour");
var sentryMonoBehaviour = sentryGameObject.GetComponent<SentryMonoBehaviour>();

Assert.IsNotNull(sentryGameObject);
Assert.IsNotNull(sentryMonoBehaviour);
}
}
}
8 changes: 5 additions & 3 deletions test/Sentry.Unity.Tests/Stubs/TestApplication.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using Sentry.Unity.Integrations;
using UnityEngine;
using UnityEngine.TestTools.Constraints;

namespace Sentry.Unity.Tests.Stubs
{
Expand All @@ -12,13 +11,16 @@ public TestApplication(
string productName = "",
string version = "",
string persistentDataPath = "",
bool isMainThread = true)
bool isMainThread = true,
RuntimePlatform platform = RuntimePlatform.WindowsEditor
)
{
IsEditor = isEditor;
ProductName = productName;
Version = version;
PersistentDataPath = persistentDataPath;
IsMainThread = isMainThread;
Platform = platform;
}

public event Application.LogCallback? LogMessageReceived;
Expand All @@ -29,7 +31,7 @@ public TestApplication(
public string Version { get; }
public string PersistentDataPath { get; }
public bool IsMainThread { get; }

public RuntimePlatform Platform { get; }
private void OnQuitting() => Quitting?.Invoke();

private void OnLogMessageReceived(string condition, string stacktrace, LogType type)
Expand Down