mirror of
https://github.com/Earth-Genesis-Games/Ajedrez_Purgatorio.git
synced 2026-09-11 09:47:35 +00:00
- Duel flow: mating piece vs boss while board collapses (PurgatoryDuelManager/Rules/UI/MuerteQuotes) - GameState.PurgatoryDuel + CampaignManager rescue/restart hooks + SquareClick routing - Dice-based rescue of most valuable dead identity; final defeat restarts Chapter 1 - 6 SFX clips wired in Ch1/2/3 via AudioClipAssigner - OptionsMenuController runtime audio/graphics panel, wired to MainMenu - Tests migrated to Assets/Tests/EditMode subfolders + PurgatoryDuelRulesTests (200 total) - Editor tools: DiagAssign, SpeakerDatabaseSetup, PurgatoryCanvasMaintenance
358 lines
12 KiB
C#
358 lines
12 KiB
C#
using NUnit.Framework;
|
|
using UnityEngine;
|
|
using AjedrezPurgatorio.Meta;
|
|
using AjedrezPurgatorio.Data;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
|
|
namespace AjedrezPurgatorio.Tests.Unit.Meta
|
|
{
|
|
/// <summary>
|
|
/// Unit tests for the DeadKingPool system.
|
|
/// Tests: AddDeadKing, GetRandomDeadKing, ShouldSpawnDeadKing,
|
|
/// FIFO rotation, content filtering, persistence.
|
|
/// </summary>
|
|
[TestFixture]
|
|
public class DeadKingPoolTests
|
|
{
|
|
private DeadKingPool _pool;
|
|
private string _testFilePath;
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
// Create a test instance of DeadKingPool
|
|
_pool = ScriptableObject.CreateInstance<DeadKingPool>();
|
|
|
|
// Mock persistent file path for testing
|
|
_testFilePath = Path.Combine(Application.temporaryCachePath, "test_dead_kings.json");
|
|
|
|
// Clear any existing test file
|
|
if (File.Exists(_testFilePath))
|
|
File.Delete(_testFilePath);
|
|
|
|
// Redirigir la ruta persistente al archivo de prueba: sin esto el pool
|
|
// cargaría el dead_kings.json real del jugador y los tests no serían
|
|
// deterministas.
|
|
SetPersistentPath(_pool, _testFilePath);
|
|
|
|
// Initialize the pool (will load from empty state)
|
|
_pool.Reinitialize();
|
|
}
|
|
|
|
[TearDown]
|
|
public void Teardown()
|
|
{
|
|
// Clean up test file
|
|
if (File.Exists(_testFilePath))
|
|
File.Delete(_testFilePath);
|
|
|
|
// Destroy test pool instance
|
|
if (_pool != null)
|
|
Object.DestroyImmediate(_pool);
|
|
}
|
|
|
|
private static void SetPersistentPath(DeadKingPool pool, string path)
|
|
{
|
|
var field = typeof(DeadKingPool).GetField("_persistentFilePath",
|
|
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
Assert.IsNotNull(field, "_persistentFilePath no encontrado en DeadKingPool.");
|
|
field.SetValue(pool, path);
|
|
}
|
|
|
|
#region AddDeadKing Tests
|
|
|
|
[Test]
|
|
public void AddDeadKing_AddsToPool()
|
|
{
|
|
// Arrange
|
|
var testDK = CreateTestDeadKing("TestPlayer", "Test message", 1, 3);
|
|
|
|
// Act
|
|
_pool.AddDeadKing(testDK);
|
|
|
|
// Assert
|
|
Assert.AreEqual(1, _pool.Count, "Pool should contain 1 Dead King after adding");
|
|
}
|
|
|
|
[Test]
|
|
public void AddDeadKing_WithNullData_LogsErrorAndDoesNotAdd()
|
|
{
|
|
// Assert (log esperado antes del Act)
|
|
UnityEngine.TestTools.LogAssert.Expect(LogType.Error, "[DeadKingPool] Cannot add null Dead King data.");
|
|
|
|
// Act
|
|
_pool.AddDeadKing(null);
|
|
|
|
// Assert
|
|
Assert.AreEqual(0, _pool.Count, "Pool should remain empty when adding null data");
|
|
}
|
|
|
|
[Test]
|
|
public void AddDeadKing_WithEmptyName_UsesAnonimo()
|
|
{
|
|
// Arrange
|
|
var testDK = CreateTestDeadKing("", "Test message", 1, 3);
|
|
|
|
// Act
|
|
_pool.AddDeadKing(testDK);
|
|
var retrieved = _pool.GetRandomDeadKing();
|
|
|
|
// Assert
|
|
Assert.AreEqual("Anónimo", retrieved.playerName, "Empty name should default to 'Anónimo'");
|
|
}
|
|
|
|
[Test]
|
|
public void AddDeadKing_FiltersProfanity_InName()
|
|
{
|
|
// Arrange
|
|
var testDK = CreateTestDeadKing("TestFuckPlayer", "Clean message", 1, 3);
|
|
|
|
// Act
|
|
_pool.AddDeadKing(testDK);
|
|
var retrieved = _pool.GetRandomDeadKing();
|
|
|
|
// Assert
|
|
Assert.IsTrue(retrieved.playerName.Contains("***"), "Profanity in name should be filtered");
|
|
Assert.IsFalse(retrieved.playerName.Contains("Fuck"), "Original profanity should not appear");
|
|
}
|
|
|
|
[Test]
|
|
public void AddDeadKing_FiltersProfanity_InMessage()
|
|
{
|
|
// Arrange
|
|
var testDK = CreateTestDeadKing("TestPlayer", "This shit is hard", 1, 3);
|
|
|
|
// Act
|
|
_pool.AddDeadKing(testDK);
|
|
var retrieved = _pool.GetRandomDeadKing();
|
|
|
|
// Assert
|
|
Assert.IsTrue(retrieved.message.Contains("***"), "Profanity in message should be filtered");
|
|
Assert.IsFalse(retrieved.message.Contains("shit"), "Original profanity should not appear");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region FIFO Rotation Tests
|
|
|
|
[Test]
|
|
public void AddDeadKing_WhenPoolFull_RemovesOldest()
|
|
{
|
|
// Arrange: Fill pool to max capacity (assuming max is 100)
|
|
// For testing, we'll use reflection to set a smaller max size or add many DKs
|
|
// Simplified: Add 101 DKs and verify the first one is removed
|
|
|
|
// Add 100 DKs
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
var dk = CreateTestDeadKing($"Player{i}", $"Message {i}", 0, i);
|
|
_pool.AddDeadKing(dk);
|
|
}
|
|
|
|
Assert.AreEqual(100, _pool.Count, "Pool should be at max capacity (100)");
|
|
|
|
// Act: Add one more (should trigger FIFO removal)
|
|
var newDK = CreateTestDeadKing("NewPlayer", "New message", 2, 5);
|
|
_pool.AddDeadKing(newDK);
|
|
|
|
// Assert
|
|
Assert.AreEqual(100, _pool.Count, "Pool should still be at max capacity after FIFO");
|
|
|
|
// Verify the new DK is in the pool
|
|
var allDKs = _pool.GetAllDeadKings();
|
|
bool containsNew = allDKs.Exists(dk => dk.playerName == "NewPlayer");
|
|
Assert.IsTrue(containsNew, "Newly added DK should be in the pool");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetRandomDeadKing Tests
|
|
|
|
[Test]
|
|
public void GetRandomDeadKing_WhenPoolEmpty_ReturnsNull()
|
|
{
|
|
// Act
|
|
var result = _pool.GetRandomDeadKing();
|
|
|
|
// Assert
|
|
Assert.IsNull(result, "Should return null when pool is empty");
|
|
}
|
|
|
|
[Test]
|
|
public void GetRandomDeadKing_WhenPoolHasOne_ReturnsThatOne()
|
|
{
|
|
// Arrange
|
|
var testDK = CreateTestDeadKing("OnlyPlayer", "Only message", 1, 3);
|
|
_pool.AddDeadKing(testDK);
|
|
|
|
// Act
|
|
var result = _pool.GetRandomDeadKing();
|
|
|
|
// Assert
|
|
Assert.IsNotNull(result, "Should return a Dead King");
|
|
Assert.AreEqual("OnlyPlayer", result.playerName, "Should return the only Dead King in pool");
|
|
}
|
|
|
|
[Test]
|
|
public void GetRandomDeadKing_WhenPoolHasMultiple_ReturnsRandomly()
|
|
{
|
|
// Arrange: Add 10 different DKs
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
var dk = CreateTestDeadKing($"Player{i}", $"Message {i}", 0, i);
|
|
_pool.AddDeadKing(dk);
|
|
}
|
|
|
|
// Act: Get multiple random DKs and verify we get different ones
|
|
var results = new HashSet<string>();
|
|
for (int i = 0; i < 20; i++)
|
|
{
|
|
var dk = _pool.GetRandomDeadKing();
|
|
results.Add(dk.playerName);
|
|
}
|
|
|
|
// Assert: We should have gotten more than 1 unique DK (randomness)
|
|
Assert.Greater(results.Count, 1, "Should return different Dead Kings over multiple calls");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ShouldSpawnDeadKing Tests
|
|
|
|
[Test]
|
|
public void ShouldSpawnDeadKing_WhenPoolEmpty_ReturnsFalse()
|
|
{
|
|
// Act
|
|
bool shouldSpawn = _pool.ShouldSpawnDeadKing(0);
|
|
|
|
// Assert
|
|
Assert.IsFalse(shouldSpawn, "Should not spawn when pool is empty");
|
|
}
|
|
|
|
[Test]
|
|
public void ShouldSpawnDeadKing_Chapter0_HasBaseChance()
|
|
{
|
|
// Arrange: Add one DK
|
|
_pool.AddDeadKing(CreateTestDeadKing("Test", "Test", 0, 0));
|
|
|
|
// Act: Run spawn check many times to verify probability
|
|
int spawnCount = 0;
|
|
int iterations = 1000;
|
|
|
|
for (int i = 0; i < iterations; i++)
|
|
{
|
|
if (_pool.ShouldSpawnDeadKing(0))
|
|
spawnCount++;
|
|
}
|
|
|
|
// Assert: Should be around 20% (0.2 base chance)
|
|
float spawnRate = (float)spawnCount / iterations;
|
|
Assert.Greater(spawnRate, 0.10f, "Spawn rate should be greater than 10%");
|
|
Assert.Less(spawnRate, 0.30f, "Spawn rate should be less than 30%");
|
|
// Expected: ~20% with some variance
|
|
}
|
|
|
|
[Test]
|
|
public void ShouldSpawnDeadKing_Chapter1_HasHigherChance()
|
|
{
|
|
// Arrange
|
|
_pool.AddDeadKing(CreateTestDeadKing("Test", "Test", 0, 0));
|
|
|
|
// Act
|
|
int spawnCount = 0;
|
|
int iterations = 1000;
|
|
|
|
for (int i = 0; i < iterations; i++)
|
|
{
|
|
if (_pool.ShouldSpawnDeadKing(1))
|
|
spawnCount++;
|
|
}
|
|
|
|
// Assert: Should be around 40% (0.2 base + 0.2 * 1)
|
|
float spawnRate = (float)spawnCount / iterations;
|
|
Assert.Greater(spawnRate, 0.30f, "Ch1 spawn rate should be higher than base");
|
|
Assert.Less(spawnRate, 0.50f, "Ch1 spawn rate should be less than 50%");
|
|
}
|
|
|
|
[Test]
|
|
public void ShouldSpawnDeadKing_Chapter2_HasEvenHigherChance()
|
|
{
|
|
// Arrange
|
|
_pool.AddDeadKing(CreateTestDeadKing("Test", "Test", 0, 0));
|
|
|
|
// Act
|
|
int spawnCount = 0;
|
|
int iterations = 1000;
|
|
|
|
for (int i = 0; i < iterations; i++)
|
|
{
|
|
if (_pool.ShouldSpawnDeadKing(2))
|
|
spawnCount++;
|
|
}
|
|
|
|
// Assert: Should be around 60% (0.2 base + 0.2 * 2)
|
|
float spawnRate = (float)spawnCount / iterations;
|
|
Assert.Greater(spawnRate, 0.50f, "Ch2 spawn rate should be ~60%");
|
|
Assert.Less(spawnRate, 0.70f, "Ch2 spawn rate should be less than 70%");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Persistence Tests
|
|
|
|
[Test]
|
|
public void SaveAndLoad_Roundtrip_PreservesData()
|
|
{
|
|
// Arrange: Add multiple DKs
|
|
_pool.AddDeadKing(CreateTestDeadKing("Player1", "Message1", 1, 3));
|
|
_pool.AddDeadKing(CreateTestDeadKing("Player2", "Message2", 2, 5));
|
|
|
|
// Act: Save
|
|
_pool.SavePool();
|
|
|
|
// Create new pool instance and load from the SAME redirected test file
|
|
var newPool = ScriptableObject.CreateInstance<DeadKingPool>();
|
|
SetPersistentPath(newPool, _testFilePath);
|
|
newPool.Reinitialize();
|
|
newPool.LoadPool();
|
|
|
|
// Assert: Data should match
|
|
Assert.AreEqual(_pool.Count, newPool.Count, "Loaded pool should have same count");
|
|
|
|
var originalDKs = _pool.GetAllDeadKings();
|
|
var loadedDKs = newPool.GetAllDeadKings();
|
|
|
|
for (int i = 0; i < originalDKs.Count; i++)
|
|
{
|
|
Assert.AreEqual(originalDKs[i].playerName, loadedDKs[i].playerName, $"DK {i} name should match");
|
|
Assert.AreEqual(originalDKs[i].message, loadedDKs[i].message, $"DK {i} message should match");
|
|
Assert.AreEqual(originalDKs[i].chapterReached, loadedDKs[i].chapterReached, $"DK {i} chapter should match");
|
|
}
|
|
|
|
// Cleanup
|
|
Object.DestroyImmediate(newPool);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helper Methods
|
|
|
|
/// <summary>
|
|
/// Creates a test Dead King with specified data.
|
|
/// </summary>
|
|
private DeadKingData CreateTestDeadKing(string name, string message, int chapter, int piecesLost)
|
|
{
|
|
return new DeadKingData(
|
|
name,
|
|
message,
|
|
chapter,
|
|
piecesLost,
|
|
new CampaignStats(50, 10, 2, 1)
|
|
);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|