Skip to content

Commit

Permalink
Merge pull request #79 from nowsprinting/feature/screenshot_unique_ag…
Browse files Browse the repository at this point in the history
…entname

Change UGUIMonkeyAgent default screenshot filename strategy to TwoTieredCounterStrategy
  • Loading branch information
asurato authored Oct 21, 2024
2 parents 0550148 + e15ac9d commit a021e22
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 15 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ Note that it is convenient to set the `[CreateAssetMenu]` attribute to create an

### Game title-specific pre-processing

If your title requires its own initialization process, add the `InitializeOnLaunchAutopilot` attribute to the `public static` method that does the initialization.
If your title requires its own initialization process, add the `InitializeOnLaunchAutopilot` attribute to the `static` method that does the initialization.
An added method is called from the autopilot launch process.

```csharp
Expand All @@ -496,7 +496,7 @@ Async methods are also supported.

```csharp
[InitializeOnLaunchAutopilot]
public static async UniTask InitializeOnLaunchAutopilotMethod()
private static async UniTask InitializeOnLaunchAutopilotMethod()
{
// initialize code for your game.
}
Expand Down
4 changes: 2 additions & 2 deletions README_ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ Assembly Definition File (asmdef) のAuto Referencedをoff、Define Constraints

### タイトル独自事前処理

タイトル独自の初期化処理が必要な場合、初期化を行なう `public static` メソッドに `InitializeOnLaunchAutopilot` 属性を付与してください。
タイトル独自の初期化処理が必要な場合、初期化を行なう `static` メソッドに `InitializeOnLaunchAutopilot` 属性を付与してください。
オートパイロットの起動処理の中でメソッドを呼び出します。

```csharp
Expand All @@ -499,7 +499,7 @@ public static void InitializeOnLaunchAutopilotMethod()

```csharp
[InitializeOnLaunchAutopilot]
public static async UniTask InitializeOnLaunchAutopilotMethod()
private static async UniTask InitializeOnLaunchAutopilotMethod()
{
// プロジェクト固有の初期化処理
}
Expand Down
4 changes: 2 additions & 2 deletions Runtime/Agents/UGUIMonkeyAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Cysharp.Threading.Tasks;
using DeNA.Anjin.Strategies;
using TestHelper.Monkey;
using TestHelper.Monkey.Annotations.Enums;
using TestHelper.Monkey.Operators;
using TestHelper.Monkey.Random;
using TestHelper.Monkey.ScreenshotFilenameStrategies;
using TestHelper.Random;
using UnityEngine;

Expand Down Expand Up @@ -112,7 +112,7 @@ public override async UniTask Run(CancellationToken token)
? new ScreenshotOptions
{
Directory = defaultScreenshotDirectory ? null : screenshotDirectory,
FilenameStrategy = new CounterBasedStrategy(
FilenameStrategy = new TwoTieredCounterStrategy(
defaultScreenshotFilenamePrefix ? this.name : screenshotFilenamePrefix
),
SuperSize = screenshotSuperSize,
Expand Down
4 changes: 3 additions & 1 deletion Runtime/Launcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using DeNA.Anjin.Attributes;
Expand Down Expand Up @@ -59,9 +60,10 @@ public static async UniTaskVoid Run()

private static async UniTask CallAttachedInitializeOnLaunchAutopilotAttributeMethods()
{
const BindingFlags MethodBindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
foreach (var methodInfo in AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.SelectMany(x => x.GetMethods())
.SelectMany(x => x.GetMethods(MethodBindingFlags))
.Where(x => x.GetCustomAttributes(typeof(InitializeOnLaunchAutopilotAttribute), false).Any()))
{
switch (methodInfo.ReturnType.Name)
Expand Down
3 changes: 3 additions & 0 deletions Runtime/Strategies.meta

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

58 changes: 58 additions & 0 deletions Runtime/Strategies/TwoTieredCounterStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) 2023-2024 DeNA Co., Ltd.
// This software is released under the MIT License.

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using DeNA.Anjin.Attributes;
using TestHelper.Monkey.ScreenshotFilenameStrategies;

namespace DeNA.Anjin.Strategies
{
/// <summary>
/// Screenshot filename strategy that adds a unique counter to the prefix.
/// </summary>
public class TwoTieredCounterStrategy : AbstractPrefixAndUniqueIDStrategy
{
private static readonly Dictionary<string, int> s_prefixCounters = new Dictionary<string, int>();
private readonly int _uniqueNumberOfPrefix;
private int _count;

[InitializeOnLaunchAutopilot]
internal static void ResetPrefixCounters()
{
s_prefixCounters.Clear();
}

/// <inheritdoc/>
[SuppressMessage("ReSharper", "CanSimplifyDictionaryLookupWithTryAdd")]
public TwoTieredCounterStrategy(string filenamePrefix = null, [CallerMemberName] string callerMemberName = null)
: base(filenamePrefix, callerMemberName)
{
var key = base.GetFilenamePrefix();
if (s_prefixCounters.ContainsKey(key))
{
s_prefixCounters[key]++;
}
else
{
s_prefixCounters[key] = 1;
}

_uniqueNumberOfPrefix = s_prefixCounters[key];
_count = 0;
}

/// <inheritdoc/>
protected override string GetFilenamePrefix()
{
return $"{base.GetFilenamePrefix()}{_uniqueNumberOfPrefix:D2}";
}

/// <inheritdoc/>
protected override string GetUniqueID()
{
return $"{++_count:D4}";
}
}
}
3 changes: 3 additions & 0 deletions Runtime/Strategies/TwoTieredCounterStrategy.cs.meta

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

2 changes: 1 addition & 1 deletion Tests/Runtime/Agents/UGUIMonkeyAgentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public async Task Run_lifespanPassed_stopAgent()
public async Task Run_DefaultScreenshotFilenamePrefix_UseAgentName()
{
const string AgentName = "MyMonkeyAgent";
var filename = $"{AgentName}_0001.png";
var filename = $"{AgentName}01_0001.png";
var path = Path.Combine(_defaultOutputDirectory, filename);
if (File.Exists(path))
{
Expand Down
3 changes: 2 additions & 1 deletion Tests/Runtime/DeNA.Anjin.Tests.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"UniTask",
"DeNA.Anjin.Editor",
"TestHelper",
"TestHelper.RuntimeInternals"
"TestHelper.RuntimeInternals",
"TestHelper.Monkey"
],
"includePlatforms": [],
"excludePlatforms": [],
Expand Down
17 changes: 15 additions & 2 deletions Tests/Runtime/LauncherTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public async Task Launch_InitializeOnLaunchAutopilotAttribute_Called()
}

[Test]
public async Task Launch_InitializeOnLaunchAutopilotAttributeAttachToAsyncMethod_Called()
public async Task Launch_InitializeOnLaunchAutopilotAttributeAttachToNonPublicMethod_Called()
{
SpyInitializeOnLaunchAutopilot.Reset();

Expand All @@ -103,7 +103,20 @@ public async Task Launch_InitializeOnLaunchAutopilotAttributeAttachToAsyncMethod
settings.lifespanSec = 1;
await LauncherFromTest.AutopilotAsync(settings); // TODO: Renamed in another PR

Assert.That(SpyInitializeOnLaunchAutopilot.IsCallInitializeOnLaunchAutopilotMethodAsync, Is.True);
Assert.That(SpyInitializeOnLaunchAutopilot.IsCallInitializeOnLaunchAutopilotMethodNonPublic, Is.True);
}

[Test]
public async Task Launch_InitializeOnLaunchAutopilotAttributeAttachToTaskAsyncMethod_Called()
{
SpyInitializeOnLaunchAutopilot.Reset();

var settings = ScriptableObject.CreateInstance(typeof(AutopilotSettings)) as AutopilotSettings;
settings.sceneAgentMaps = new List<SceneAgentMap>();
settings.lifespanSec = 1;
await LauncherFromTest.AutopilotAsync(settings); // TODO: Renamed in another PR

Assert.That(SpyInitializeOnLaunchAutopilot.IsCallInitializeOnLaunchAutopilotMethodTaskAsync, Is.True);
}

[Test]
Expand Down
3 changes: 3 additions & 0 deletions Tests/Runtime/Strategies.meta

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

58 changes: 58 additions & 0 deletions Tests/Runtime/Strategies/TwoTieredCounterStrategyTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) 2023-2024 DeNA Co., Ltd.
// This software is released under the MIT License.

using NUnit.Framework;

namespace DeNA.Anjin.Strategies
{
public class TwoTieredCounterStrategyTest
{
[SetUp]
public void SetUp()
{
TwoTieredCounterStrategy.ResetPrefixCounters();
}

[Test]
public void GetFilename_WithPrefix_ReturnsUniqueFilename()
{
var sut = new TwoTieredCounterStrategy("MyPrefix");

Assert.That(sut.GetFilename(), Is.EqualTo("MyPrefix01_0001.png"));
Assert.That(sut.GetFilename(), Is.EqualTo("MyPrefix01_0002.png"));
}

[Test]
public void GetFilename_WithoutPrefix_ReturnsFilenameUsingTestName()
{
var sut = new TwoTieredCounterStrategy();

Assert.That(sut.GetFilename(), Is.EqualTo($"{TestContext.CurrentContext.Test.Name}01_0001.png"));
Assert.That(sut.GetFilename(), Is.EqualTo($"{TestContext.CurrentContext.Test.Name}01_0002.png"));
}

[Test]
public void GetFilename_WithSamePrefix_ReturnsFilenameUsingUniqueNumberByPrefix()
{
var sut = new TwoTieredCounterStrategy("MyPrefix");
var sut2 = new TwoTieredCounterStrategy("MyPrefix");

Assert.That(sut.GetFilename(), Is.EqualTo("MyPrefix01_0001.png"));
Assert.That(sut.GetFilename(), Is.EqualTo("MyPrefix01_0002.png"));
Assert.That(sut2.GetFilename(), Is.EqualTo("MyPrefix02_0001.png"));
Assert.That(sut2.GetFilename(), Is.EqualTo("MyPrefix02_0002.png"));
}

[Test]
public void GetFilename_WithAnotherPrefix_ReturnsUniqueFilenameByPrefix()
{
var sut = new TwoTieredCounterStrategy("MyPrefix");
var sut2 = new TwoTieredCounterStrategy("AnotherPrefix");

Assert.That(sut.GetFilename(), Is.EqualTo("MyPrefix01_0001.png"));
Assert.That(sut.GetFilename(), Is.EqualTo("MyPrefix01_0002.png"));
Assert.That(sut2.GetFilename(), Is.EqualTo("AnotherPrefix01_0001.png"));
Assert.That(sut2.GetFilename(), Is.EqualTo("AnotherPrefix01_0002.png"));
}
}
}
3 changes: 3 additions & 0 deletions Tests/Runtime/Strategies/TwoTieredCounterStrategyTest.cs.meta

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

16 changes: 12 additions & 4 deletions Tests/Runtime/TestDoubles/SpyInitializeOnLaunchAutopilot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ namespace DeNA.Anjin.TestDoubles
public static class SpyInitializeOnLaunchAutopilot
{
public static bool IsCallInitializeOnLaunchAutopilotMethod { get; private set; }
public static bool IsCallInitializeOnLaunchAutopilotMethodAsync { get; private set; }
public static bool IsCallInitializeOnLaunchAutopilotMethodNonPublic { get; private set; }
public static bool IsCallInitializeOnLaunchAutopilotMethodTaskAsync { get; private set; }
public static bool IsCallInitializeOnLaunchAutopilotMethodUniTaskAsync { get; private set; }

public static void Reset()
{
IsCallInitializeOnLaunchAutopilotMethod = false;
IsCallInitializeOnLaunchAutopilotMethodAsync = false;
IsCallInitializeOnLaunchAutopilotMethodNonPublic = false;
IsCallInitializeOnLaunchAutopilotMethodTaskAsync = false;
IsCallInitializeOnLaunchAutopilotMethodUniTaskAsync = false;
}

Expand All @@ -27,10 +29,16 @@ public static void InitializeOnLaunchAutopilotMethod()
}

[InitializeOnLaunchAutopilot]
public static async Task InitializeOnLaunchAutopilotMethodAsync()
private static void InitializeOnLaunchAutopilotMethodNonPublic()
{
IsCallInitializeOnLaunchAutopilotMethodNonPublic = true;
}

[InitializeOnLaunchAutopilot]
public static async Task InitializeOnLaunchAutopilotMethodTaskAsync()
{
await Task.Delay(0);
IsCallInitializeOnLaunchAutopilotMethodAsync = true;
IsCallInitializeOnLaunchAutopilotMethodTaskAsync = true;
}

[InitializeOnLaunchAutopilot]
Expand Down

0 comments on commit a021e22

Please sign in to comment.