fix: refresh the retained on-air scene
This commit is contained in:
@@ -458,7 +458,7 @@ public sealed class DynamicK3dSessionTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateOnAir_UsesPlayingSceneAndAppliesOnlyBeforeTransactionBackgroundSetup()
|
||||
public async Task UpdateOnAir_ReusesRetainedSceneAndIgnoresInvalidPlayingSceneProxy()
|
||||
{
|
||||
using var scenes = TemporarySceneDirectory.Create(
|
||||
"test-scene.t2s",
|
||||
@@ -484,7 +484,7 @@ public sealed class DynamicK3dSessionTests
|
||||
]));
|
||||
var log = new FakeComLog();
|
||||
var scene = new FakeScene(log, "test-scene");
|
||||
var player = new FakePlayer(log) { PlayingScene = scene };
|
||||
var player = new FakePlayer(log) { PlayingScene = new object() };
|
||||
var activator = new FakeActivator(log, new FakeEngine(log, player, scene));
|
||||
await using var dispatcher = new StaDispatcher(capacity: 2);
|
||||
var updateStart = 0;
|
||||
@@ -514,7 +514,6 @@ public sealed class DynamicK3dSessionTests
|
||||
Assert.Equal(
|
||||
new[]
|
||||
{
|
||||
"GetPlayingScene:10",
|
||||
"UseBackground:0",
|
||||
"SetBackgroundTexture:background.vrv",
|
||||
"SetBackgroundVideo:background.vrv:4:1",
|
||||
@@ -531,20 +530,274 @@ public sealed class DynamicK3dSessionTests
|
||||
"Play:10"
|
||||
},
|
||||
updateCalls);
|
||||
Assert.Equal(1, updateCalls.Count(call => call == "Play:10"));
|
||||
Assert.DoesNotContain("GetPlayingScene:10", log.Names);
|
||||
Assert.DoesNotContain(updateCalls, call =>
|
||||
call.StartsWith("LoadScene:", StringComparison.Ordinal) ||
|
||||
call.StartsWith("SetSceneEffectType:", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateOnAir_CallbackSession_TracksItsPlayUntilMatchingCallback()
|
||||
public async Task UpdateOnAir_MismatchedRetainedSceneFailsBeforeAnySdkMutation()
|
||||
{
|
||||
using var scenes = TemporarySceneDirectory.Create(
|
||||
"5001.t2s",
|
||||
"5006.t2s",
|
||||
"Video\\background.vrv");
|
||||
var options = SceneOptions(scenes.Path, "5001", "5006");
|
||||
var initialCue = SceneCue(options, "5001");
|
||||
var mismatchedCue = options.ResolveCue(new PlayoutCue(
|
||||
"5006.t2s",
|
||||
"5006",
|
||||
[new PlayoutField("headline", "must not be sent", true)],
|
||||
Mutations:
|
||||
[
|
||||
new PlayoutUseBackground(false),
|
||||
new PlayoutSetBackgroundTexture("Video/background.vrv")
|
||||
]));
|
||||
var log = new FakeComLog();
|
||||
var retainedScene = new FakeScene(log, "5001");
|
||||
var player = new FakePlayer(log) { PlayingScene = new object() };
|
||||
var activator = new FakeActivator(
|
||||
log,
|
||||
new FakeEngine(log, player, retainedScene));
|
||||
await using var dispatcher = new StaDispatcher(capacity: 2);
|
||||
string[] updateCalls = [];
|
||||
|
||||
await dispatcher.InvokeAsync(
|
||||
() =>
|
||||
{
|
||||
using var session = new DynamicK3dSession(activator);
|
||||
session.Connect(options);
|
||||
session.Prepare(initialCue, options.LayoutIndex);
|
||||
session.Play(options.LayoutIndex);
|
||||
|
||||
var updateStart = log.Names.Length;
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => session.UpdateOnAir(mismatchedCue, options.LayoutIndex));
|
||||
updateCalls = log.Names.Skip(updateStart).ToArray();
|
||||
session.Disconnect();
|
||||
return true;
|
||||
},
|
||||
TimeSpan.FromSeconds(5),
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.Empty(updateCalls);
|
||||
Assert.DoesNotContain("GetPlayingScene:10", log.Names);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateOnAir_WithoutRetainedCurrentSceneFailsBeforeAnySdkMutation()
|
||||
{
|
||||
using var scenes = TemporarySceneDirectory.Create("5001.t2s");
|
||||
var options = SceneOptions(scenes.Path, "5001");
|
||||
var cue = SceneCue(options, "5001");
|
||||
var log = new FakeComLog();
|
||||
var player = new FakePlayer(log) { PlayingScene = new object() };
|
||||
var scene = new FakeScene(log, "5001");
|
||||
var activator = new FakeActivator(log, new FakeEngine(log, player, scene));
|
||||
await using var dispatcher = new StaDispatcher(capacity: 2);
|
||||
string[] updateCalls = [];
|
||||
|
||||
await dispatcher.InvokeAsync(
|
||||
() =>
|
||||
{
|
||||
using var session = new DynamicK3dSession(activator);
|
||||
session.Connect(options);
|
||||
|
||||
var updateStart = log.Names.Length;
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => session.UpdateOnAir(cue, options.LayoutIndex));
|
||||
updateCalls = log.Names.Skip(updateStart).ToArray();
|
||||
session.Disconnect();
|
||||
return true;
|
||||
},
|
||||
TimeSpan.FromSeconds(5),
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.Empty(updateCalls);
|
||||
Assert.DoesNotContain("GetPlayingScene:10", log.Names);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateOnAir_WithAnotherPreparedSceneFailsBeforeAnySdkMutation()
|
||||
{
|
||||
using var scenes = TemporarySceneDirectory.Create("5001.t2s", "5006.t2s");
|
||||
var options = SceneOptions(scenes.Path, "5001", "5006");
|
||||
var cue5001 = SceneCue(options, "5001");
|
||||
var log = new FakeComLog();
|
||||
var player = new FakePlayer(log) { PlayingScene = new object() };
|
||||
var scene5001 = new FakeScene(log, "5001");
|
||||
var scene5006 = new FakeScene(log, "5006");
|
||||
var engine = new FakeEngine(log, player, scene5001)
|
||||
{
|
||||
SceneResolver = name => name == "5006" ? scene5006 : scene5001
|
||||
};
|
||||
var activator = new FakeActivator(log, engine);
|
||||
await using var dispatcher = new StaDispatcher(capacity: 2);
|
||||
string[] updateCalls = [];
|
||||
|
||||
await dispatcher.InvokeAsync(
|
||||
() =>
|
||||
{
|
||||
using var session = new DynamicK3dSession(activator);
|
||||
session.Connect(options);
|
||||
session.Prepare(cue5001, options.LayoutIndex);
|
||||
session.Play(options.LayoutIndex);
|
||||
session.Prepare(SceneCue(options, "5006"), options.LayoutIndex);
|
||||
|
||||
var updateStart = log.Names.Length;
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => session.UpdateOnAir(cue5001, options.LayoutIndex));
|
||||
updateCalls = log.Names.Skip(updateStart).ToArray();
|
||||
session.Disconnect();
|
||||
return true;
|
||||
},
|
||||
TimeSpan.FromSeconds(5),
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.Empty(updateCalls);
|
||||
Assert.DoesNotContain("GetPlayingScene:10", log.Names);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateOnAir_WithPendingInitialPlayFailsBeforeAnySdkMutation()
|
||||
{
|
||||
using var scenes = TemporarySceneDirectory.Create("5001.t2s");
|
||||
var options = SceneOptions(scenes.Path, "5001");
|
||||
var cue = SceneCue(options, "5001");
|
||||
var log = new FakeComLog();
|
||||
var scene = new FakeScene(log, "5001");
|
||||
var player = new FakePlayer(log) { PlayingScene = scene };
|
||||
var player = new FakePlayer(log) { PlayingScene = new object() };
|
||||
var engine = new FakeEngine(log, player, scene);
|
||||
var activator = new FakeActivator(log, engine);
|
||||
var callbacks = new RecordingEventHandlerFactory();
|
||||
var releaser = new FakeReleaser(
|
||||
log,
|
||||
(scene, "5001"),
|
||||
(player, "Player"),
|
||||
(engine, "Engine"),
|
||||
(callbacks.Handler, "EventHandler"));
|
||||
await using var dispatcher = new StaDispatcher(capacity: 2);
|
||||
string[] updateCalls = [];
|
||||
|
||||
await dispatcher.InvokeAsync(
|
||||
() =>
|
||||
{
|
||||
using var session = new DynamicK3dSession(
|
||||
activator,
|
||||
releaser,
|
||||
new InstalledK3dInteropMethodInvoker(),
|
||||
callbacks);
|
||||
session.Connect(options);
|
||||
session.Prepare(cue, options.LayoutIndex);
|
||||
session.Play(options.LayoutIndex);
|
||||
Assert.True(session.HasPendingPlayCallbacks);
|
||||
|
||||
var updateStart = log.Names.Length;
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => session.UpdateOnAir(cue, options.LayoutIndex));
|
||||
updateCalls = log.Names.Skip(updateStart).ToArray();
|
||||
|
||||
callbacks.Fire("OnScenePlayed", 1, 9, options.LayoutIndex);
|
||||
session.ProcessPendingCallbacks(options.LayoutIndex);
|
||||
Assert.False(session.HasPendingPlayCallbacks);
|
||||
session.Disconnect();
|
||||
return true;
|
||||
},
|
||||
TimeSpan.FromSeconds(5),
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.Empty(updateCalls);
|
||||
Assert.DoesNotContain("GetPlayingScene:10", log.Names);
|
||||
Assert.Equal(1, log.Names.Count(name => name == "Release:5001"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateOnAir_TransactionFailureRollsBackAndRetainsSceneForStopAllCleanup()
|
||||
{
|
||||
using var scenes = TemporarySceneDirectory.Create("5001.t2s");
|
||||
var options = SceneOptions(scenes.Path, "5001");
|
||||
var initialCue = SceneCue(options, "5001");
|
||||
var updateCue = options.ResolveCue(new PlayoutCue(
|
||||
"5001.t2s",
|
||||
"5001",
|
||||
[new PlayoutField("headline", "refresh", true)],
|
||||
Mutations: [new PlayoutUseBackground(false)]));
|
||||
var log = new FakeComLog();
|
||||
var scene = new FakeScene(log, "5001");
|
||||
var player = new FakePlayer(log) { PlayingScene = new object() };
|
||||
var engine = new FakeEngine(log, player, scene);
|
||||
var activator = new FakeActivator(log, engine);
|
||||
var callbacks = new RecordingEventHandlerFactory();
|
||||
var releaser = new FakeReleaser(
|
||||
log,
|
||||
(scene, "5001"),
|
||||
(player, "Player"),
|
||||
(engine, "Engine"),
|
||||
(callbacks.Handler, "EventHandler"));
|
||||
await using var dispatcher = new StaDispatcher(capacity: 2);
|
||||
|
||||
await dispatcher.InvokeAsync(
|
||||
() =>
|
||||
{
|
||||
using var session = new DynamicK3dSession(
|
||||
activator,
|
||||
releaser,
|
||||
new InstalledK3dInteropMethodInvoker(),
|
||||
callbacks);
|
||||
session.Connect(options);
|
||||
session.Prepare(initialCue, options.LayoutIndex);
|
||||
session.Play(options.LayoutIndex);
|
||||
callbacks.Fire("OnScenePlayed", 1, 9, options.LayoutIndex);
|
||||
session.ProcessPendingCallbacks(options.LayoutIndex);
|
||||
|
||||
scene.QueryVariablesFailure = new InvalidOperationException("fake refresh failure");
|
||||
var updateStart = log.Names.Length;
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => session.UpdateOnAir(updateCue, options.LayoutIndex));
|
||||
var updateCalls = log.Names.Skip(updateStart).ToArray();
|
||||
Assert.Equal(
|
||||
new[]
|
||||
{
|
||||
"UseBackground:0",
|
||||
"BeginTransaction",
|
||||
"GetObject:headline",
|
||||
"SetValue:headline:refresh",
|
||||
"SetVisible:headline:1",
|
||||
"QueryVariables",
|
||||
"RollbackTransaction"
|
||||
},
|
||||
updateCalls);
|
||||
Assert.DoesNotContain("Release:5001", log.Names);
|
||||
Assert.DoesNotContain("Unload:5001", log.Names);
|
||||
|
||||
scene.QueryVariablesFailure = null;
|
||||
session.TakeOut(options.LayoutIndex, PlayoutTakeOutScope.All);
|
||||
callbacks.Fire("OnStopAll", 1);
|
||||
Assert.Equal(
|
||||
1,
|
||||
session.ProcessPendingCallbacks(options.LayoutIndex).UnloadedSceneCount);
|
||||
session.Disconnect();
|
||||
return true;
|
||||
},
|
||||
TimeSpan.FromSeconds(5),
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.Equal(1, log.Names.Count(name => name == "Unload:5001"));
|
||||
Assert.Equal(1, log.Names.Count(name => name == "Release:5001"));
|
||||
Assert.DoesNotContain("GetPlayingScene:10", log.Names);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateOnAir_CallbackSession_TracksPlayAndRetainsSceneUntilStopAll()
|
||||
{
|
||||
using var scenes = TemporarySceneDirectory.Create("5001.t2s");
|
||||
var options = SceneOptions(scenes.Path, "5001");
|
||||
var cue = SceneCue(options, "5001");
|
||||
var log = new FakeComLog();
|
||||
var scene = new FakeScene(log, "5001");
|
||||
var player = new FakePlayer(log) { PlayingScene = new object() };
|
||||
var engine = new FakeEngine(log, player, scene);
|
||||
var activator = new FakeActivator(log, engine);
|
||||
var callbacks = new RecordingEventHandlerFactory();
|
||||
@@ -577,6 +830,8 @@ public sealed class DynamicK3dSessionTests
|
||||
|
||||
session.UpdateOnAir(cue, options.LayoutIndex);
|
||||
Assert.True(session.HasPendingLifecycleCallbacks);
|
||||
Assert.DoesNotContain("Release:5001", log.Names);
|
||||
Assert.DoesNotContain("Unload:5001", log.Names);
|
||||
|
||||
callbacks.Fire("OnScenePlayed", 1, 8, 10);
|
||||
session.ProcessPendingCallbacks(options.LayoutIndex);
|
||||
@@ -585,6 +840,13 @@ public sealed class DynamicK3dSessionTests
|
||||
callbacks.Fire("OnScenePlayed", 1, 9, 10);
|
||||
session.ProcessPendingCallbacks(options.LayoutIndex);
|
||||
Assert.False(session.HasPendingLifecycleCallbacks);
|
||||
|
||||
session.TakeOut(options.LayoutIndex, PlayoutTakeOutScope.All);
|
||||
callbacks.Fire("OnStopAll", 1);
|
||||
Assert.Equal(
|
||||
1,
|
||||
session.ProcessPendingCallbacks(options.LayoutIndex).UnloadedSceneCount);
|
||||
Assert.False(session.HasPendingLifecycleCallbacks);
|
||||
session.Disconnect();
|
||||
return true;
|
||||
},
|
||||
@@ -592,8 +854,9 @@ public sealed class DynamicK3dSessionTests
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.Equal(2, log.Names.Count(name => name == "Play:10"));
|
||||
Assert.Equal(1, log.Names.Count(name => name == "GetPlayingScene:10"));
|
||||
Assert.DoesNotContain("Unload:5001", log.Names);
|
||||
Assert.DoesNotContain("GetPlayingScene:10", log.Names);
|
||||
Assert.Equal(1, log.Names.Count(name => name == "Unload:5001"));
|
||||
Assert.Equal(1, log.Names.Count(name => name == "Release:5001"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -1729,7 +1992,7 @@ public sealed class DynamicK3dSessionTests
|
||||
{
|
||||
private readonly FakeComLog _log;
|
||||
private readonly string? _name;
|
||||
private readonly Exception? _queryVariablesFailure;
|
||||
private Exception? _queryVariablesFailure;
|
||||
private readonly Exception? _unloadFailure;
|
||||
|
||||
public FakeScene(
|
||||
@@ -1773,6 +2036,12 @@ public sealed class DynamicK3dSessionTests
|
||||
}
|
||||
}
|
||||
|
||||
public Exception? QueryVariablesFailure
|
||||
{
|
||||
get => _queryVariablesFailure;
|
||||
set => _queryVariablesFailure = value;
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
_log.Add(_name is null ? "Unload" : $"Unload:{_name}");
|
||||
|
||||
Reference in New Issue
Block a user