Skip to content

Commit

Permalink
Refactor pull up _autopilot fields to AbstractAgent
Browse files Browse the repository at this point in the history
  • Loading branch information
nowsprinting committed Nov 30, 2024
1 parent c99c6ca commit 54ad38b
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 66 deletions.
22 changes: 20 additions & 2 deletions Runtime/Agents/AbstractAgent.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) 2023 DeNA Co., Ltd.
// Copyright (c) 2023-2024 DeNA Co., Ltd.
// This software is released under the MIT License.

using System.Threading;
using DeNA.Anjin.Utilities;
using Cysharp.Threading.Tasks;
using DeNA.Anjin.Utilities;
using UnityEngine;

namespace DeNA.Anjin.Agents
Expand All @@ -30,6 +30,24 @@ public abstract class AbstractAgent : ScriptableObject
/// </summary>
public virtual IRandom Random { get; set; }

private ITerminatable _autopilotInstance;

/// <summary>
/// Running Autopilot instance.
/// Can inject a spy object for testing.
/// </summary>
public ITerminatable AutopilotInstance
{
get
{
return _autopilotInstance ?? Autopilot.Instance;
}
set
{
_autopilotInstance = value;
}
}

/// <summary>
/// Run agent
/// </summary>
Expand Down
15 changes: 6 additions & 9 deletions Runtime/Agents/ErrorHandlerAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
using System.Threading;
using Cysharp.Threading.Tasks;
Expand Down Expand Up @@ -62,9 +63,7 @@ public class ErrorHandlerAgent : AbstractAgent
/// </summary>
public string[] ignoreMessages = new string[] { };

internal ITerminatable _autopilot; // can inject for testing
private List<Regex> _ignoreMessagesRegexes;
private CancellationToken _token;

[InitializeOnLaunchAutopilot]
private static void ResetInstances()
Expand All @@ -73,16 +72,12 @@ private static void ResetInstances()
var agents = Resources.FindObjectsOfTypeAll<ErrorHandlerAgent>();
foreach (var agent in agents)
{
agent._autopilot = null;
agent._ignoreMessagesRegexes = null;
agent._token = default;
}
}

public override async UniTask Run(CancellationToken token)
{
this._token = token;

try
{
Logger.Log($"Enter {this.name}.Run()");
Expand All @@ -106,6 +101,7 @@ public override async UniTask Run(CancellationToken token)
/// <param name="logString">Log message string</param>
/// <param name="stackTrace">Stack trace</param>
/// <param name="type">Log message type</param>
[SuppressMessage("ReSharper", "AsyncVoidMethod")] // Called by Application.logMessageReceivedThreaded
internal async void HandleLog(string logString, string stackTrace, LogType type)
{
var handlingBehavior = JudgeHandlingBehavior(logString, stackTrace, type);
Expand All @@ -128,12 +124,13 @@ internal async void HandleLog(string logString, string stackTrace, LogType type)
throw new InvalidOperationException("Autopilot is not running");
}

await settings.Reporter.PostReportAsync(logString, stackTrace, exitCode, this._token);
// ReSharper disable once MethodSupportsCancellation; Do not use this Agent's CancellationToken.
settings.Reporter.PostReportAsync(logString, stackTrace, exitCode).Forget();
}
else
{
_autopilot = _autopilot ?? Autopilot.Instance;
await _autopilot.TerminateAsync(exitCode, logString, stackTrace, token: this._token);
// ReSharper disable once MethodSupportsCancellation; Do not use this Agent's CancellationToken.
AutopilotInstance.TerminateAsync(exitCode, logString, stackTrace).Forget();
}
}

Expand Down
21 changes: 2 additions & 19 deletions Runtime/Agents/TerminateAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Cysharp.Threading.Tasks;
using DeNA.Anjin.Attributes;
using UnityEngine;

namespace DeNA.Anjin.Agents
Expand Down Expand Up @@ -72,31 +71,15 @@ public ExitCode ExitCode
[Multiline]
public string exitMessage = "Terminated by TerminateAgent";

internal ITerminatable _autopilot; // can inject for testing

[InitializeOnLaunchAutopilot]
private static void ResetInstances()
{
// Reset runtime instances
var agents = Resources.FindObjectsOfTypeAll<TerminateAgent>();
foreach (var agent in agents)
{
agent._autopilot = null;
}
}

/// <inheritdoc/>
public override async UniTask Run(CancellationToken token)
{
try
{
Logger.Log($"Enter {this.name}.Run()");

_autopilot = _autopilot ?? Autopilot.Instance;

// ReSharper disable once MethodSupportsCancellation
_autopilot.TerminateAsync(ExitCode, exitMessage).Forget();
// Note: Do not use this Agent's CancellationToken.
// ReSharper disable once MethodSupportsCancellation; Do not use this Agent's CancellationToken.
AutopilotInstance.TerminateAsync(ExitCode, exitMessage).Forget();
}
finally
{
Expand Down
27 changes: 13 additions & 14 deletions Runtime/Agents/TimeBombAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ public class TimeBombAgent : AbstractAgent
/// </summary>
public string defuseMessage;

internal ITerminatable _autopilot; // can inject for testing
private CancellationTokenSource _cts;
#pragma warning disable IDISP006
private CancellationTokenSource _agentCts; // dispose in using block
#pragma warning restore IDISP006
private Regex _defuseMessageRegex;

private Regex DefuseMessageRegex
Expand All @@ -57,8 +58,8 @@ private static void ResetInstances()
var agents = Resources.FindObjectsOfTypeAll<TimeBombAgent>();
foreach (var agent in agents)
{
agent._autopilot = null;
agent._cts = null;
agent._agentCts?.Dispose();
agent._agentCts = null;
agent.DefuseMessageRegex = null;
}
}
Expand All @@ -79,7 +80,7 @@ private void HandleDefuseMessage(string logString, string stackTrace, LogType ty
{
try
{
_cts?.Cancel();
_agentCts?.Cancel();
}
catch (ObjectDisposedException)
{
Expand All @@ -95,28 +96,26 @@ public override async UniTask Run(CancellationToken token)

try
{
using (var agentCts = new CancellationTokenSource()) // To cancel only the Working Agent.
using (_agentCts = new CancellationTokenSource()) // To cancel only the Working Agent.
{
_cts = agentCts;

using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(token, agentCts.Token))
using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(token, _agentCts.Token))
{
try
{
agent.Logger = Logger;
agent.Random = Random;
// Note: This Agent does not consume pseudo-random numbers, so passed on as is.

await agent.Run(linkedCts.Token);

// If the working Agent exits first, the TimeBombAgent will fail.
var message =
$"Could not receive defuse message `{defuseMessage}` before the {agent.name} terminated.";
Logger.Log(message);
_autopilot = _autopilot ?? Autopilot.Instance;
// ReSharper disable once MethodSupportsCancellation
_autopilot.TerminateAsync(ExitCode.AutopilotFailed, message,
new StackTrace(true).ToString())
.Forget(); // Note: Do not use this Agent's CancellationToken.

// ReSharper disable once MethodSupportsCancellation; Do not use this Agent's CancellationToken.
AutopilotInstance.TerminateAsync(ExitCode.AutopilotFailed, message,
new StackTrace(true).ToString()).Forget();
}
catch (OperationCanceledException)
{
Expand Down
21 changes: 3 additions & 18 deletions Runtime/Agents/UGUIMonkeyAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Cysharp.Threading.Tasks;
using DeNA.Anjin.Attributes;
using DeNA.Anjin.Settings;
using DeNA.Anjin.Strategies;
using TestHelper.Monkey;
Expand Down Expand Up @@ -98,19 +97,6 @@ public class UGUIMonkeyAgent : AbstractAgent
public ScreenCapture.StereoScreenCaptureMode screenshotStereoCaptureMode =
ScreenCapture.StereoScreenCaptureMode.LeftEye;

internal ITerminatable _autopilot; // can inject for testing

[InitializeOnLaunchAutopilot]
private static void ResetInstances()
{
// Reset runtime instances
var agents = Resources.FindObjectsOfTypeAll<UGUIMonkeyAgent>();
foreach (var agent in agents)
{
agent._autopilot = null;
}
}

/// <inheritdoc />
public override async UniTask Run(CancellationToken token)
{
Expand Down Expand Up @@ -155,10 +141,9 @@ public override async UniTask Run(CancellationToken token)
{
var message = $"{e.GetType().Name}: {e.Message}";
Logger.Log(message);
_autopilot = _autopilot ?? Autopilot.Instance;
// ReSharper disable once MethodSupportsCancellation
_autopilot.TerminateAsync(ExitCode.AutopilotFailed, message, e.StackTrace)
.Forget(); // Note: Do not use this Agent's CancellationToken.

// ReSharper disable once MethodSupportsCancellation; Do not use this Agent's CancellationToken.
AutopilotInstance.TerminateAsync(ExitCode.AutopilotFailed, message, e.StackTrace).Forget();
}
finally
{
Expand Down
2 changes: 1 addition & 1 deletion Tests/Runtime/Agents/ErrorHandlerAgentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void SetUp()
_spyLoggerAsset = ScriptableObject.CreateInstance<SpyLoggerAsset>();

_sut = ScriptableObject.CreateInstance<ErrorHandlerAgent>();
_sut._autopilot = _spyTerminatable;
_sut.AutopilotInstance = _spyTerminatable;
_sut.Logger = _spyLoggerAsset.Logger;

_spyReporter = ScriptableObject.CreateInstance<SpyReporter>();
Expand Down
2 changes: 1 addition & 1 deletion Tests/Runtime/Agents/TerminateAgentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public async Task Run_CallTerminateAsync()
agent.exitMessage = "Terminated!";

var spyTerminatable = new SpyTerminatable();
agent._autopilot = spyTerminatable;
agent.AutopilotInstance = spyTerminatable;

using (var cts = new CancellationTokenSource())
{
Expand Down
2 changes: 1 addition & 1 deletion Tests/Runtime/Agents/TimeBombAgentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public async Task Run_NotDefuse_AutopilotFailed()
var monkeyAgent = CreateMonkeyAgent(1);
var agent = CreateTimeBombAgent(monkeyAgent, "^Never match!$");
var spyTerminatable = new SpyTerminatable();
agent._autopilot = spyTerminatable;
agent.AutopilotInstance = spyTerminatable;

using (var cts = new CancellationTokenSource())
{
Expand Down
2 changes: 1 addition & 1 deletion Tests/Runtime/Agents/UGUIMonkeyAgentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public async Task Run_TimeoutExceptionOccurred_AutopilotFailed()
agent.secondsToErrorForNoInteractiveComponent = 1; // TimeoutException occurred after 1 second

var spyTerminatable = new SpyTerminatable();
agent._autopilot = spyTerminatable;
agent.AutopilotInstance = spyTerminatable;

using (var cts = new CancellationTokenSource())
{
Expand Down

0 comments on commit 54ad38b

Please sign in to comment.