285 lines
10 KiB
C#
285 lines
10 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using NUnit.Framework;
|
|
using Unity.Pipeline.Editor.BuildProcessors;
|
|
using UnityEditor;
|
|
using UnityEditor.Build;
|
|
using UnityEditor.Build.Reporting;
|
|
using UnityEditor.SceneManagement;
|
|
using UnityEditor.TestTools;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.Pipeline.Tests.Editor
|
|
{
|
|
/// <summary>
|
|
/// Tests for Pipeline runtime build support using RuntimePipelineManager.
|
|
/// Validates build processor behavior and scene-based configuration detection.
|
|
/// </summary>
|
|
public class RuntimePipelineBuildTests
|
|
{
|
|
private string m_TestScenePath;
|
|
private string m_BuildDirectory;
|
|
private PipelineRuntimeBuildProcessor m_BuildProcessor;
|
|
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
// Create test scene path
|
|
m_TestScenePath = "Assets/TestRuntimePipelineScene.unity";
|
|
m_BuildDirectory = $"TestBuild/{GetType().Name}";
|
|
m_BuildProcessor = new PipelineRuntimeBuildProcessor();
|
|
|
|
// Clean up any existing test files
|
|
if (File.Exists(m_TestScenePath))
|
|
{
|
|
AssetDatabase.DeleteAsset(m_TestScenePath);
|
|
}
|
|
|
|
if (Directory.Exists(m_BuildDirectory))
|
|
{
|
|
Directory.Delete(m_BuildDirectory, true);
|
|
}
|
|
}
|
|
|
|
[TearDown]
|
|
public void TearDown()
|
|
{
|
|
// Clean up test scene
|
|
if (File.Exists(m_TestScenePath))
|
|
{
|
|
AssetDatabase.DeleteAsset(m_TestScenePath);
|
|
}
|
|
|
|
// Clean up build directory
|
|
if (Directory.Exists(m_BuildDirectory))
|
|
{
|
|
Directory.Delete(m_BuildDirectory, true);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void BuildProcessor_RuntimeManagerDisabled_LogsDisabledMessage()
|
|
{
|
|
// Arrange - Create scene with disabled RuntimePipelineManager
|
|
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
|
var go = new GameObject("RuntimePipelineManager");
|
|
var manager = go.AddComponent<RuntimePipelineManager>();
|
|
manager.enableInBuilds = false; // Disabled
|
|
|
|
EditorSceneManager.SaveScene(scene, m_TestScenePath);
|
|
|
|
var originalScenes = EditorBuildSettings.scenes;
|
|
EditorBuildSettings.scenes = new[] { new EditorBuildSettingsScene(m_TestScenePath, true) };
|
|
|
|
try
|
|
{
|
|
var mockReport = CreateMockBuildReport();
|
|
|
|
// Act & Assert
|
|
Assert.DoesNotThrow(() => m_BuildProcessor.OnPreprocessBuild(mockReport));
|
|
}
|
|
finally
|
|
{
|
|
EditorBuildSettings.scenes = originalScenes;
|
|
Object.DestroyImmediate(go);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void BuildProcessor_RuntimeManagerEnabled_ValidatesConfiguration()
|
|
{
|
|
// Arrange - Create scene with enabled RuntimePipelineManager
|
|
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
|
var go = new GameObject("RuntimePipelineManager");
|
|
var manager = go.AddComponent<RuntimePipelineManager>();
|
|
|
|
// Configure with valid settings
|
|
manager.enableInBuilds = true;
|
|
|
|
EditorSceneManager.SaveScene(scene, m_TestScenePath);
|
|
|
|
var originalScenes = EditorBuildSettings.scenes;
|
|
EditorBuildSettings.scenes = new[] { new EditorBuildSettingsScene(m_TestScenePath, true) };
|
|
|
|
try
|
|
{
|
|
var mockReport = CreateMockBuildReport();
|
|
|
|
// Act & Assert - Should not throw with valid configuration
|
|
Assert.DoesNotThrow(() => m_BuildProcessor.OnPreprocessBuild(mockReport));
|
|
}
|
|
finally
|
|
{
|
|
EditorBuildSettings.scenes = originalScenes;
|
|
Object.DestroyImmediate(go);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void BuildProcessor_MultipleManagers_UsesFirstEnabled()
|
|
{
|
|
// Arrange - Create scene with multiple RuntimePipelineManagers
|
|
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
|
|
|
// First manager - disabled
|
|
var go1 = new GameObject("DisabledManager");
|
|
var manager1 = go1.AddComponent<RuntimePipelineManager>();
|
|
manager1.enableInBuilds = false;
|
|
|
|
// Second manager - enabled
|
|
var go2 = new GameObject("EnabledManager");
|
|
var manager2 = go2.AddComponent<RuntimePipelineManager>();
|
|
manager2.enableInBuilds = true;
|
|
|
|
EditorSceneManager.SaveScene(scene, m_TestScenePath);
|
|
|
|
var originalScenes = EditorBuildSettings.scenes;
|
|
EditorBuildSettings.scenes = new[] { new EditorBuildSettingsScene(m_TestScenePath, true) };
|
|
|
|
try
|
|
{
|
|
var mockReport = CreateMockBuildReport();
|
|
|
|
// Act & Assert - Should use the enabled manager without throwing
|
|
Assert.DoesNotThrow(() => m_BuildProcessor.OnPreprocessBuild(mockReport));
|
|
}
|
|
finally
|
|
{
|
|
EditorBuildSettings.scenes = originalScenes;
|
|
Object.DestroyImmediate(go1);
|
|
Object.DestroyImmediate(go2);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a mock BuildReport for testing build processor.
|
|
/// </summary>
|
|
#if UNITY_6000_3_OR_NEWER
|
|
private BuildCallbackContext CreateMockBuildReport()
|
|
#else
|
|
private BuildReport CreateMockBuildReport()
|
|
#endif
|
|
{
|
|
// Note: BuildReport is sealed and cannot be easily mocked
|
|
// In a real implementation, we'd need a wrapper or different approach
|
|
// For now, we'll use reflection or test with null if the processor handles it
|
|
return null; // Build processor doesn't actually use the report parameter
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Platform-specific build tests following Unity test patterns.
|
|
/// Tests actual build generation with RuntimePipelineManager.
|
|
/// </summary>
|
|
[RequirePlatformSupport(BuildTarget.StandaloneWindows64)]
|
|
public class RuntimePipelineWindows64BuildTests : RuntimePipelineBuildTestBase
|
|
{
|
|
protected override BuildTarget Target => BuildTarget.StandaloneWindows64;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Abstract base class for build generation tests.
|
|
/// Follows Unity test patterns for build validation.
|
|
/// </summary>
|
|
public abstract class RuntimePipelineBuildTestBase
|
|
{
|
|
protected abstract BuildTarget Target { get; }
|
|
protected string BuildDirectory => $"TestBuild/{GetType().Name}";
|
|
|
|
[OneTimeSetUp]
|
|
public void OneTimeSetUp()
|
|
{
|
|
// Clean up from any previous test runs
|
|
if (Directory.Exists(BuildDirectory))
|
|
{
|
|
Directory.Delete(BuildDirectory, true);
|
|
}
|
|
}
|
|
|
|
[OneTimeTearDown]
|
|
public void OneTimeTearDown()
|
|
{
|
|
// Clean up after tests
|
|
if (Directory.Exists(BuildDirectory))
|
|
{
|
|
Directory.Delete(BuildDirectory, true);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void BuildPlayerWithRuntimeManager_ValidConfiguration_BuildSucceeds()
|
|
{
|
|
// Skip if platform support not available
|
|
if (!IsPlatformSupportInstalled(Target))
|
|
{
|
|
Assert.Ignore($"Platform support for {Target} is not installed");
|
|
}
|
|
|
|
// Note: When calling BuildPlayer the list of scene is ALWAYS overridden with what is in the current build profile
|
|
var testScenePath = CreateTestSceneWithRuntimeManager(validConfiguration: true);
|
|
|
|
try
|
|
{
|
|
var buildOptions = new BuildPlayerOptions
|
|
{
|
|
scenes = new[] { testScenePath },
|
|
locationPathName = Path.Combine(BuildDirectory, "TestBuild.exe"),
|
|
target = Target,
|
|
options = BuildOptions.Development // Use development for faster builds
|
|
};
|
|
|
|
// Act - Build player
|
|
var report = BuildPipeline.BuildPlayer(buildOptions);
|
|
|
|
// Assert - Build succeeded
|
|
Assert.AreEqual(BuildResult.Succeeded, report.summary.result,
|
|
$"Build should succeed: {string.Join("; ", report.steps.SelectMany(s => s.messages).Select(m => m.content))}");
|
|
|
|
// Verify output files exist
|
|
var outputFiles = report.GetFiles();
|
|
Assert.IsTrue(outputFiles.Any(), "Build should produce output files");
|
|
|
|
// Verify executable exists
|
|
Assert.IsTrue(File.Exists(buildOptions.locationPathName), "Executable should exist after successful build");
|
|
}
|
|
finally
|
|
{
|
|
// Clean up test scene
|
|
AssetDatabase.DeleteAsset(testScenePath);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a test scene with RuntimePipelineManager component.
|
|
/// </summary>
|
|
protected string CreateTestSceneWithRuntimeManager(bool validConfiguration)
|
|
{
|
|
var scenePath = $"Assets/TestScene_{Target}_{System.Guid.NewGuid():N}.unity";
|
|
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
|
|
|
|
var go = new GameObject("RuntimePipelineManager");
|
|
var manager = go.AddComponent<RuntimePipelineManager>();
|
|
|
|
manager.enableInBuilds = validConfiguration;
|
|
|
|
EditorSceneManager.SaveScene(scene, scenePath);
|
|
return scenePath;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if platform support is installed for the target.
|
|
/// </summary>
|
|
protected bool IsPlatformSupportInstalled(BuildTarget target)
|
|
{
|
|
try
|
|
{
|
|
var group = BuildPipeline.GetBuildTargetGroup(target);
|
|
return true; // If we can get the group, platform support is available
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
} |