251 lines
10 KiB
C#
Raw Normal View History

2025-03-11 15:30:07 +08:00
using System.Collections;
using UnityEngine;
using UnityEditor;
using NUnit.Framework;
using UnityEditor.Build.Reporting;
using System.IO;
using UnityEngine.TestTools;
using System.Diagnostics;
namespace Autodesk.Fbx.BuildTests
{
internal class BuildTest
{
private const string k_fbxsdkNativePlugin = "UnityFbxSdkNative";
private const string k_autodeskFbxDll = "Autodesk.Fbx.dll";
#if UNITY_EDITOR_WIN
private const string k_fbxsdkNativePluginExt = ".dll";
private const string k_buildPluginPath = "{0}_Data";
private const BuildTarget k_buildTarget = BuildTarget.StandaloneWindows64;
private const string k_autodeskDllInstallPath = "Managed";
#elif UNITY_EDITOR_OSX
private const string k_fbxsdkNativePluginExt = ".bundle";
private const string k_buildPluginPath = "{0}.app/Contents";
private const BuildTarget k_buildTarget = BuildTarget.StandaloneOSX;
private const string k_autodeskDllInstallPath = "Resources/Data/Managed";
#else // UNITY_EDITOR_LINUX
private const string k_fbxsdkNativePluginExt = ".so";
private const string k_buildPluginPath = "{0}_Data";
private const BuildTarget k_buildTarget = BuildTarget.StandaloneLinux64;
private const string k_autodeskDllInstallPath = "Managed";
#endif
private const BuildTargetGroup k_buildTargetGroup = BuildTargetGroup.Standalone;
private const string k_buildTestScene = "Packages/com.autodesk.fbx/Tests/Runtime/BuildTestsAssets/BuildTestScene.unity";
private const string k_createdFbx = "emptySceneFromRuntimeBuild.fbx";
private const string k_runningBuildSymbol = "FBX_RUNNING_BUILD_TEST";
#if UNITY_EDITOR_LINUX
private const string k_buildName = "test.x86_64";
#else
private const string k_buildName = "test.exe";
#endif
private string BuildFolder { get { return Path.Combine(Path.GetDirectoryName(Application.dataPath), "_safe_to_delete_build"); } }
public static IEnumerable RuntimeFbxSdkTestData
{
get
{
yield return new TestCaseData(
new string[] { k_runningBuildSymbol },
false,
ScriptingImplementation.Mono2x
).SetName("FbxSdkNotIncludedAtRuntime_Mono").Returns(null);
yield return new TestCaseData(
new string[] { k_runningBuildSymbol, "FBXSDK_RUNTIME" },
true,
ScriptingImplementation.Mono2x
).SetName("FbxSdkIncludedAtRuntime_Mono").Returns(null);
#if !UNITY_EDITOR_LINUX || UNITY_2019_3_OR_NEWER
yield return new TestCaseData(
new string[] { k_runningBuildSymbol },
false,
ScriptingImplementation.IL2CPP
).SetName("FbxSdkNotIncludedAtRuntime_IL2CPP").Returns(null);
yield return new TestCaseData(
new string[] { k_runningBuildSymbol, "FBXSDK_RUNTIME" },
true,
ScriptingImplementation.IL2CPP
).SetName("FbxSdkIncludedAtRuntime_IL2CPP").Returns(null);
#endif // !UNITY_EDITOR_LINUX || UNITY_2019_3_OR_NEWER
}
}
[SetUp]
public void Init()
{
// Create build folder
Directory.CreateDirectory(BuildFolder);
}
[TearDown]
public void Term()
{
// reset the scripting define symbols
var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(k_buildTargetGroup);
// remove the running build symbol and everything after it
var result = symbols.Split(new string[] { k_runningBuildSymbol, ";" + k_runningBuildSymbol }, System.StringSplitOptions.None);
PlayerSettings.SetScriptingDefineSymbolsForGroup(k_buildTargetGroup, result[0]);
// set scripting backend back to default (Mono)
PlayerSettings.SetScriptingBackend(k_buildTargetGroup, ScriptingImplementation.Mono2x);
// delete build folder
if (Directory.Exists(BuildFolder))
{
Directory.Delete(BuildFolder, recursive: true);
}
}
private BuildReport BuildPlayer()
{
BuildPlayerOptions options = new BuildPlayerOptions();
options.locationPathName = Path.Combine(BuildFolder, k_buildName);
options.target = k_buildTarget;
options.targetGroup = k_buildTargetGroup;
options.scenes = new string[] { k_buildTestScene };
var report = BuildPipeline.BuildPlayer(options);
Assert.That(report.summary.result, Is.EqualTo(BuildResult.Succeeded));
return report;
}
private void AddDefineSymbols(string[] toAdd)
{
if (toAdd.Length <= 0)
{
return;
}
var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(k_buildTargetGroup);
if (!string.IsNullOrEmpty(symbols))
{
symbols += ";";
}
symbols += toAdd[0];
for (int i = 1; i < toAdd.Length; i++)
{
symbols += ";" + toAdd[i];
}
PlayerSettings.SetScriptingDefineSymbolsForGroup(k_buildTargetGroup, symbols);
}
[Ignore("Ignoring in CI because we don't control which backends are installed")]
[UnityTest]
[TestCaseSource("RuntimeFbxSdkTestData")]
public IEnumerator TestFbxSdkAtRuntime(string[] defineSymbols, bool dllExists, ScriptingImplementation scriptingImplementation)
{
PlayerSettings.SetScriptingBackend(k_buildTargetGroup, scriptingImplementation);
AddDefineSymbols(defineSymbols);
// start and stop playmode to force a domain reload
Assert.False(Application.isPlaying);
yield return new EnterPlayMode();
Assert.True(Application.isPlaying);
yield return new ExitPlayMode();
Assert.False(Application.isPlaying);
var report = BuildPlayer();
// check whether the plugins were copied
var buildPathWithoutExt = Path.ChangeExtension(report.summary.outputPath, null);
var buildPluginFullPath = Path.Combine(
string.Format(k_buildPluginPath, buildPathWithoutExt),
"Plugins",
#if UNITY_EDITOR_LINUX
"x86_64",
#endif
k_fbxsdkNativePlugin + k_fbxsdkNativePluginExt
);
NUnit.Framework.Constraints.Constraint constraint = Does.Not.Exist;
if (dllExists)
{
constraint = Does.Exist;
}
Assert.That(buildPluginFullPath, constraint);
// Autodesk.Fbx.dll will not exist if building with IL2CPP
if(scriptingImplementation != ScriptingImplementation.IL2CPP)
{
// check the size of Autodesk.Fbx.dll
var autodeskDllFullPath = Path.Combine(
string.Format(k_buildPluginPath, buildPathWithoutExt),
k_autodeskDllInstallPath,
k_autodeskFbxDll
);
Assert.That(autodeskDllFullPath, Does.Exist);
var fileInfo = new FileInfo(autodeskDllFullPath);
// If the FBX SDK is copied over at runtime, the DLL filesize will
// be ~350,000. If it isn't copied over it will be ~3500.
// Putting the expected size as 10000 to allow for some buffer room.
var expectedDllFileSize = 10000;
if (dllExists)
{
Assert.That(fileInfo.Length, Is.GreaterThan(expectedDllFileSize));
}
else
{
Assert.That(fileInfo.Length, Is.LessThan(expectedDllFileSize));
}
}
var buildPath = report.summary.outputPath;
#if UNITY_EDITOR_OSX
buildPath = Path.ChangeExtension(buildPath, "app");
buildPath = Path.Combine(buildPath, "Contents", "MacOS");
// on Unity 2018.4, the path to the executable is:
// test.app/Contents/MacOS/test
// whereas in later versions, the path is:
// test.app/Contents/MacOS/{product_name}
#if UNITY_2018_4
buildPath = Path.Combine(buildPath, Path.GetFileNameWithoutExtension(k_buildName));
#else // UNITY_2018_4
buildPath = Path.Combine(buildPath, Application.productName);
#endif // UNITY_2018_4
#endif // UNITY_EDITOR_OSX
Process p = new Process();
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.FileName = buildPath;
p.StartInfo.Arguments = "-batchmode -nographics";
p.StartInfo.UseShellExecute = true;
p.Start();
// Wait for 10 seconds for application to run.
// If it doesn't finish by then something has probably
// gone wrong, like the export script gave an error or wasn't
// included in the build.
bool hasExited = p.WaitForExit(10000);
if (!hasExited)
{
p.Kill();
Assert.Fail(string.Format("Process running {0} timed out", buildPath));
}
// Check that the FBX was created
var buildPluginFbxPath = Path.Combine(
string.Format(k_buildPluginPath, buildPathWithoutExt),
k_createdFbx
);
// Make sure the constraint is still set properly.
// The constraint resets between this check and the previous.
constraint = Does.Not.Exist;
if (dllExists)
{
constraint = Does.Exist;
}
Assert.That(buildPluginFbxPath, constraint);
}
}
}