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
6 changes: 5 additions & 1 deletion .github/workflows/test-audience-sample-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ jobs:
changeset: 7670c08855a9
runner: [self-hosted, macOS, ARM64]
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
# Healthy cells finish in ~10 min. 30 min covers cold caches +
# IL2CPP + Unity 6 startup; anything past that is a hang. Capping
# short releases the self-hosted runner sooner so queued cells can
# progress instead of waiting 60 min on a stuck job.
timeout-minutes: 30

steps:
- name: Kill stale Unity processes (Windows pre-checkout)
Expand Down
73 changes: 73 additions & 0 deletions .github/workflows/test-audience-sdk-unity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Audience package — Unity Tests

# Runs the Unity-dependent SDK tests that test-audience-sdk.yml's csproj
# excludes (Tests/Runtime/Unity/** + Tests/Editor/**). Single GameCI Linux
# cell on iOS targetPlatform so UnityEditor.iOS.Xcode and the UNITY_IOS
# define resolve. testables is injected at CI time so the sample app's
# Packages/manifest.json doesn't permanently advertise the package's tests
# (avoids polluting the sample app workflow's PlayMode runs).

on:
push:
branches: [main]
paths:
- 'src/Packages/Audience/**'
- 'examples/audience/Packages/manifest.json'
- '.github/workflows/test-audience-sdk-unity.yml'
pull_request:
paths:
- 'src/Packages/Audience/**'
- 'examples/audience/Packages/manifest.json'
- '.github/workflows/test-audience-sdk-unity.yml'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
editmode:
if: github.event.pull_request.head.repo.fork == false || github.event_name == 'workflow_dispatch'
name: SDK EditMode (Unity 2022.3 / iOS module)
runs-on: ubuntu-latest-8-cores
timeout-minutes: 30

steps:
- uses: actions/checkout@v4
with:
lfs: true

- name: Inject testables into Packages/manifest.json
# Adds com.immutable.audience to the project's testables array so
# Unity Test Runner discovers the package's test asmdefs. Done in CI
# rather than committed to the file so the sample app workflow's
# PlayMode cells stay scoped to sample-app-only tests.
run: |
jq '.testables = (.testables // []) + ["com.immutable.audience"]' examples/audience/Packages/manifest.json > examples/audience/Packages/manifest.tmp.json
mv examples/audience/Packages/manifest.tmp.json examples/audience/Packages/manifest.json

- uses: actions/cache@v4
with:
path: examples/audience/Library
key: Library-audience-sdk-tests-${{ hashFiles('examples/audience/Packages/**', 'examples/audience/ProjectSettings/**', 'src/Packages/Audience/**') }}
restore-keys: |
Library-audience-sdk-tests-

- uses: game-ci/unity-test-runner@v4
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
with:
unityVersion: 2022.3.62f2
targetPlatform: iOS
projectPath: examples/audience
testMode: editmode
customParameters: -assemblyNames Immutable.Audience.Runtime.Tests;Immutable.Audience.Editor.Tests
checkName: Audience SDK Tests
artifactsPath: artifacts

- uses: actions/upload-artifact@v4
if: always()
with:
name: audience-sdk-test-results
path: artifacts
3 changes: 3 additions & 0 deletions src/Packages/Audience/Runtime/Unity/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Immutable.Audience.Runtime.Tests")]
11 changes: 11 additions & 0 deletions src/Packages/Audience/Runtime/Unity/AssemblyInfo.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions src/Packages/Audience/Tests/Runtime/Core/SessionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,18 +475,21 @@ public void End_HeartbeatExceedsDrainBudget_LogsWarningAndContinues()
var warnings = new List<string>();
var prevWriter = Log.Writer;
Log.Writer = line => { lock (warnings) warnings.Add(line); };
using var beatStarted = new ManualResetEvent(false);
using var releaseBeat = new ManualResetEvent(false);
try
{
using var beatStarted = new ManualResetEvent(false);
void Track(string name, Dictionary<string, object> props)
{
if (name == "session_heartbeat")
{
beatStarted.Set();
// Block past the 1 s drain budget so DrainHeartbeatTimer
// times out. Self-releases after 1.5 s so the callback
// does eventually finish.
Thread.Sleep(1500);
// times out. Generous safety cap (10 s) ensures a
// failed assertion below can't wedge the test
// process; the normal release path is the explicit
// releaseBeat.Set() in the finally block.
releaseBeat.WaitOne(TimeSpan.FromSeconds(10));
}
}

Expand All @@ -505,6 +508,7 @@ void Track(string name, Dictionary<string, object> props)
}
finally
{
releaseBeat.Set();
Log.Writer = prevWriter;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ public void CollectGameLaunchProperties_StringFields_DoNotExceed256Chars()
"platform", "version", "buildGuid", "unityVersion",
"osFamily", "deviceModel", "gpu", "gpuVendor", "cpu" })
{
if (!props.TryGetValue(key, out var val) || val is not string s) continue;
if (!props.TryGetValue(key, out var val)) continue;
if (val is not string s) continue;
Assert.LessOrEqual(s.Length, 256, $"props[{key}] exceeds 256 chars");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ public void DisposeAndWait_IdleTimer_SignalsBeforeTimeout()
[Test]
public void DisposeAndWait_LongCallback_ReturnsFalseAndLeaksHandle()
{
// Mono player builds (Unity Standalone Mono targets) signal
// Timer.Dispose's wait handle ahead of in-flight callbacks
// completing, which breaks this unit test's premise. Production
// code is unaffected — DrainHeartbeatTimer is exercised
// end-to-end by the SampleApp PlayMode tests on the same Mono
// builds and works correctly. This unit test asserts a
// lower-level WaitHandle invariant that doesn't hold under Mono.
if (Type.GetType("Mono.Runtime") != null)
Assert.Ignore("Skipped on Mono: Timer.Dispose(WaitHandle) signals before in-flight callbacks complete.");

using var release = new ManualResetEventSlim(false);
using var callbackEntered = new ManualResetEventSlim(false);

Expand Down
Loading