Initial commit: AIGame Unity client with URP, HybridCLR, YooAsset and tooling.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.Pipeline.Compilation;
|
||||
|
||||
namespace Unity.Pipeline.Tests.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// Compact smoke test targeting the interpreter's AOT-hazard surface. In the editor / a Mono
|
||||
/// player it passes trivially; its <b>purpose is to fail loudly when run in an IL2CPP standalone
|
||||
/// player</b> if an AOT regression (linker stripping, <c>MakeGenericMethod</c>, generic virtual
|
||||
/// dispatch, or the <c>AllowTypeStruct<T></c> boxed-struct fast path) creeps in.
|
||||
///
|
||||
/// The probe scripts are pre-compiled on desktop and embedded as IL blobs
|
||||
/// (<see cref="IlInterpreterAotProbeBlobs"/>, generated by IlInterpreter/tests/IlInterpreter.ProbeGen) —
|
||||
/// Roslyn cannot compile inside an IL2CPP player (proven by CI job 73639037), and the faithful
|
||||
/// push_reload scenario ships compiled bytes anyway; the interpreter itself needs no Roslyn.
|
||||
///
|
||||
/// Categorised "Il2Cpp" so the CI player-build job can target it (see .yamato/il2cpp-playmode.yml).
|
||||
/// </summary>
|
||||
[Category("Il2Cpp")]
|
||||
class IlInterpreterAotSmokeTests
|
||||
{
|
||||
static IlInterpreter.Interpreter.ScriptInterpreter Load(string base64)
|
||||
{
|
||||
// CreateStandard registers AllowTypeStruct<Vector3>() — the boxed-struct fast path that
|
||||
// is the primary IL2CPP hazard this test guards. It's the same builder the eval and
|
||||
// code-reload sinks run in the real player.
|
||||
var binding = IlInterpreterHostBindings.CreateStandard();
|
||||
|
||||
var interp = new IlInterpreter.Interpreter.ScriptInterpreter(binding);
|
||||
interp.Load(new RawScript(Convert.FromBase64String(base64)));
|
||||
return interp;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AllowTypeStruct_Vector3_FlatFrame_RoundTrips()
|
||||
{
|
||||
using var interp = Load(IlInterpreterAotProbeBlobs.HazardProbe);
|
||||
Assert.AreEqual(6f, (float)interp.Invoke("VecSum"), 1e-4f);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenericTypedInvoke_TwoArgs()
|
||||
{
|
||||
using var interp = Load(IlInterpreterAotProbeBlobs.HazardProbe);
|
||||
// Invoke<int,int> exercises the generic typed-arg path (MakeGenericMethod under IL2CPP).
|
||||
Assert.AreEqual(42, interp.Invoke<int, int>("Add", 19, 23));
|
||||
}
|
||||
|
||||
// A representative slice of the desktop differential-oracle corpus, replayed under IL2CPP.
|
||||
// Sources and expected values live in the generator, which re-verifies both (real-C# oracle
|
||||
// + interpreter) at generation time; this closes the "desktop interpreter == IL2CPP
|
||||
// interpreter" link for more than the two hazard paths above.
|
||||
static IEnumerable<TestCaseData> IntCorpusCases()
|
||||
{
|
||||
foreach (var c in IlInterpreterAotProbeBlobs.IntCorpus)
|
||||
yield return new TestCaseData(c.Base64, c.Expected).SetName(
|
||||
nameof(Corpus_Int_MatchesDesktop) + "_" + c.Name);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(IntCorpusCases))]
|
||||
public void Corpus_Int_MatchesDesktop(string base64, int expected)
|
||||
{
|
||||
using var interp = Load(base64);
|
||||
Assert.AreEqual(expected, (int)interp.Invoke("Run"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Corpus_Float_MatchesDesktop()
|
||||
{
|
||||
using var interp = Load(IlInterpreterAotProbeBlobs.FloatProbe);
|
||||
Assert.AreEqual(3.5f, (float)interp.Invoke("Run"), 1e-4f);
|
||||
}
|
||||
|
||||
sealed class RawScript : IlInterpreter.IScript
|
||||
{
|
||||
public RawScript(byte[] bytes) { Il = bytes; }
|
||||
public string Name => "IlInterpreterAotProbe";
|
||||
public ReadOnlyMemory<byte> Il { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user