上传YomovSDK
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.VersionControl;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR.Features.Mock;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using static UnityEditor.XR.OpenXR.Tests.OpenXREditorTestHelpers;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class BootConfigEditorTests : OpenXRLoaderSetup
|
||||
{
|
||||
[Test]
|
||||
public void TestCanCreateBootConfigAndroid()
|
||||
{
|
||||
TestBuildTarget(BuildTarget.Android);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCanCreateBootConfigWindows()
|
||||
{
|
||||
TestBuildTarget(BuildTarget.StandaloneWindows);
|
||||
TestBuildTarget(BuildTarget.StandaloneWindows64);
|
||||
}
|
||||
|
||||
private void TestBuildTarget(BuildTarget buildTarget)
|
||||
{
|
||||
var bootConfig = new BootConfig(buildTarget);
|
||||
bootConfig.ReadBootConfig();
|
||||
|
||||
// Check to see that we do not have the following key in the boot config
|
||||
Assert.IsFalse(bootConfig.TryGetValue("xr-sample-bootconfig-key01", out string value));
|
||||
Assert.AreEqual(value, null);
|
||||
|
||||
// Check to see that we can store a key and retrieve it.
|
||||
bootConfig.SetValueForKey("xr-sample-bootconfig-key02", "primary value");
|
||||
Assert.IsTrue(bootConfig.TryGetValue("xr-sample-bootconfig-key02", out string key02value));
|
||||
Assert.AreEqual(key02value, "primary value");
|
||||
Assert.IsTrue(bootConfig.CheckValuePairExists("xr-sample-bootconfig-key02", "primary value"));
|
||||
|
||||
// check to see that we can write the keys to the boot config and ensure that we can
|
||||
// retrieve the stored values
|
||||
bootConfig.WriteBootConfig();
|
||||
|
||||
var cloneBootConfig = new BootConfig(buildTarget);
|
||||
cloneBootConfig.ReadBootConfig();
|
||||
Assert.IsTrue(cloneBootConfig.TryGetValue("xr-sample-bootconfig-key02", out key02value));
|
||||
Assert.AreEqual(key02value, "primary value");
|
||||
Assert.IsTrue(cloneBootConfig.CheckValuePairExists("xr-sample-bootconfig-key02", "primary value"));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1c3182e62fd44cea6ebdbb5b36feec5
|
||||
timeCreated: 1677640135
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.VersionControl;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR.Features.Mock;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using static UnityEditor.XR.OpenXR.Tests.OpenXREditorTestHelpers;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class FeatureModifyingTests : OpenXRLoaderSetup
|
||||
{
|
||||
// Override AfterTest to prevent OpenXRSettings.Instance.features from getting reset.
|
||||
// This test suite destroys and restores OpenXRSettings.Instance.features manually.
|
||||
public override void AfterTest()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DuplicateSettingAssetTest()
|
||||
{
|
||||
// Local OpenXR filepath that contains the test OpenXR Package Settings.asset
|
||||
string openXRFolder = Path.GetFullPath("Packages/com.unity.xr.openxr");
|
||||
|
||||
string settingsFilePath = OpenXRPackageSettings.OpenXRPackageSettingsAssetPath();
|
||||
string metaFilePath = settingsFilePath + ".meta";
|
||||
|
||||
string testAssetName = "OpenXR Package Settings With Duplicates.testasset";
|
||||
string testAssetPath = Path.Combine(openXRFolder, "Tests", "Editor", testAssetName);
|
||||
string testMetaAssetPath = testAssetPath + ".meta";
|
||||
|
||||
// Copy in the test files (the files with duplicate settings)
|
||||
File.Delete(settingsFilePath);
|
||||
File.Delete(metaFilePath);
|
||||
File.Copy(testAssetPath, settingsFilePath);
|
||||
File.Copy(testMetaAssetPath, metaFilePath);
|
||||
|
||||
// Verify that we detect duplicates in the test file.
|
||||
Assert.IsFalse(OpenXRProjectValidation.AssetHasNoDuplicates(), "The duplicate settings on the bad asset should be detected.");
|
||||
|
||||
// Regenerate the asset (as if the user clicks on the Fix button in the validation window)
|
||||
OpenXRProjectValidation.RegenerateXRPackageSettingsAsset();
|
||||
|
||||
// Verify that there are no duplicates in the settings file now.
|
||||
Assert.IsTrue(OpenXRProjectValidation.AssetHasNoDuplicates(), "After regenerating the asset, the duplicate settings should be removed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2755597eb30ac124c861b2694debd290
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
408
Packages/com.unity.xr.openxr/Tests/Editor/FeatureSetTests.cs
Normal file
408
Packages/com.unity.xr.openxr/Tests/Editor/FeatureSetTests.cs
Normal file
@@ -0,0 +1,408 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
using static UnityEditor.XR.OpenXR.Features.OpenXRFeatureSetManager;
|
||||
using static UnityEditor.XR.OpenXR.Tests.OpenXREditorTestHelpers;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class FeatureSetTests : OpenXRLoaderSetup
|
||||
{
|
||||
const string k_KnownFeatureSetName = "Known Test";
|
||||
const string k_TestFeatureSetName = "Test Feature Set";
|
||||
const string k_TestFeatureSetNameHandAndEye = "Test Feature Set Hand and Eye Tracking";
|
||||
const string k_TestFeatureSetNameHand = "Test Feature Set Hand Tracking";
|
||||
const string k_TestFeatureSetDescription = "Test feature set";
|
||||
const string k_TestFeatureSetId = "com.unity.xr.test.featureset";
|
||||
const string k_TestFeatureSetIdTwo = "com.unity.xr.test.featureset2";
|
||||
const string k_TestFeatureSetIdThree = "com.unity.xr.test.featureset3";
|
||||
const string k_TestFeatureSetIdFour = "com.unity.xr.test.featureset4";
|
||||
|
||||
[OpenXRFeatureSet(
|
||||
FeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId
|
||||
},
|
||||
UiName = k_TestFeatureSetName,
|
||||
Description = k_TestFeatureSetDescription,
|
||||
FeatureSetId = k_TestFeatureSetId,
|
||||
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.Standalone },
|
||||
RequiredFeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId
|
||||
}
|
||||
)]
|
||||
[OpenXRFeatureSet(
|
||||
FeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
EyeGazeInteraction.featureId,
|
||||
},
|
||||
UiName = k_TestFeatureSetNameHandAndEye,
|
||||
Description = k_TestFeatureSetDescription,
|
||||
FeatureSetId = k_TestFeatureSetIdTwo,
|
||||
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.WSA },
|
||||
RequiredFeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
EyeGazeInteraction.featureId,
|
||||
}
|
||||
)]
|
||||
[OpenXRFeatureSet(
|
||||
FeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
},
|
||||
UiName = k_TestFeatureSetNameHand,
|
||||
Description = k_TestFeatureSetDescription,
|
||||
FeatureSetId = k_TestFeatureSetIdThree,
|
||||
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.WSA },
|
||||
RequiredFeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
}
|
||||
)]
|
||||
[OpenXRFeatureSet(
|
||||
FeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
EyeGazeInteraction.featureId,
|
||||
},
|
||||
UiName = k_TestFeatureSetName,
|
||||
Description = k_TestFeatureSetDescription,
|
||||
FeatureSetId = k_TestFeatureSetId,
|
||||
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.Android },
|
||||
RequiredFeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
EyeGazeInteraction.featureId,
|
||||
}
|
||||
)]
|
||||
[OpenXRFeatureSet(
|
||||
FeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
EyeGazeInteraction.featureId,
|
||||
HTCViveControllerProfile.featureId,
|
||||
OculusTouchControllerProfile.featureId,
|
||||
},
|
||||
UiName = k_TestFeatureSetName,
|
||||
Description = k_TestFeatureSetDescription,
|
||||
FeatureSetId = k_TestFeatureSetIdFour,
|
||||
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.Standalone },
|
||||
RequiredFeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
EyeGazeInteraction.featureId,
|
||||
},
|
||||
DefaultFeatureIds = new string[]
|
||||
{
|
||||
HTCViveControllerProfile.featureId,
|
||||
}
|
||||
)]
|
||||
sealed class TestFeatureSet { }
|
||||
|
||||
|
||||
public override void BeforeTest()
|
||||
{
|
||||
base.BeforeTest();
|
||||
OpenXRFeature.canSetFeatureDisabled = null;
|
||||
|
||||
InitializeFeatureSets(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the feature sets by disabling all features sets and all features
|
||||
/// </summary>
|
||||
/// <param name="addTestFeatures">True to include test features</param>
|
||||
private void InitializeFeatureSets(bool addTestFeatures)
|
||||
{
|
||||
// Initialize first with test feature sets so we can make sure all feature sets are disabled
|
||||
OpenXRFeatureSetManager.InitializeFeatureSets(true);
|
||||
|
||||
foreach (var buildTargetGroup in GetBuildTargetGroups())
|
||||
{
|
||||
// Disable all feature sets for this build target
|
||||
foreach (var featureSetInfo in FeatureSetInfosForBuildTarget(buildTargetGroup))
|
||||
{
|
||||
featureSetInfo.isEnabled = false;
|
||||
featureSetInfo.wasEnabled = false;
|
||||
OpenXREditorSettings.Instance.SetFeatureSetSelected(buildTargetGroup, featureSetInfo.featureSetId, false);
|
||||
}
|
||||
|
||||
// Disable all features for this build target
|
||||
var extInfo = FeatureHelpersInternal.GetAllFeatureInfo(buildTargetGroup);
|
||||
foreach (var ext in extInfo.Features)
|
||||
{
|
||||
ext.Feature.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If requested with no feature sets then reinitialize
|
||||
if (!addTestFeatures)
|
||||
OpenXRFeatureSetManager.InitializeFeatureSets(false);
|
||||
|
||||
foreach (var buildTargetGroup in GetBuildTargetGroups())
|
||||
{
|
||||
// No feature sets should be enabled for any build target
|
||||
Assert.IsFalse(FeatureSetInfosForBuildTarget(buildTargetGroup).Any(f => f.isEnabled));
|
||||
|
||||
// No features should be enabled
|
||||
AssertAllFeatures(buildTargetGroup, FeatureDisabled);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AfterTest()
|
||||
{
|
||||
base.AfterTest();
|
||||
OpenXRFeature.canSetFeatureDisabled = OpenXRFeatureSetManager.CanFeatureBeDisabled;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NoFeatureSetsReturnsEmptyList()
|
||||
{
|
||||
var featureSets = FeatureSetsForBuildTarget(BuildTargetGroup.iOS);
|
||||
Assert.AreEqual(0, featureSets.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FoundExpectedFeatureSets()
|
||||
{
|
||||
InitializeFeatureSets(false);
|
||||
|
||||
string[] expectedFeatureSets = new string[]
|
||||
{
|
||||
KnownFeatureSetsContent.s_MicrosoftHoloLensFeatureSetId
|
||||
};
|
||||
|
||||
var featureSets = FeatureSetsForBuildTarget(BuildTargetGroup.WSA);
|
||||
Assert.IsNotNull(featureSets);
|
||||
Assert.AreEqual(expectedFeatureSets.Length, featureSets.Count);
|
||||
|
||||
foreach (var featureSet in featureSets)
|
||||
{
|
||||
if (Array.IndexOf(expectedFeatureSets, featureSet.featureSetId) == -1)
|
||||
Assert.IsTrue(false, $"Found unexpected feature set id {featureSet.featureSetId}!");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnknownFeatureSetRerturnNull()
|
||||
{
|
||||
// For this test we do not want the test features enabled so rerun the initilization with
|
||||
InitializeFeatureSets(false);
|
||||
var foundFeatureSet = GetFeatureSetWithId(BuildTargetGroup.iOS, k_TestFeatureSetId);
|
||||
Assert.IsNull(foundFeatureSet);
|
||||
foundFeatureSet = GetFeatureSetWithId(BuildTargetGroup.Standalone, "BAD FEATURE SET ID");
|
||||
Assert.IsNull(foundFeatureSet);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OverrideKnownTestFeatureSet()
|
||||
{
|
||||
var foundFeatureSet = GetFeatureSetWithId(BuildTargetGroup.Standalone, k_TestFeatureSetId);
|
||||
Assert.IsNotNull(foundFeatureSet);
|
||||
Assert.AreEqual(0, String.Compare(foundFeatureSet.name, k_TestFeatureSetName, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NonoverrideKnownTestFeatureSet()
|
||||
{
|
||||
var foundFeatureSet = GetFeatureSetWithId(BuildTargetGroup.WSA, k_TestFeatureSetId);
|
||||
Assert.IsNotNull(foundFeatureSet);
|
||||
Assert.AreEqual(0, String.Compare(foundFeatureSet.name, k_KnownFeatureSetName, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EnableFeatureSetEnablesFeatures()
|
||||
{
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, k_TestFeatureSetId, enabled: true);
|
||||
AssertOnlyFeatures(BuildTargetGroup.Standalone, new string[] { MicrosoftHandInteraction.featureId }, FeatureEnabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisableFeatureSetDisabledFeatures()
|
||||
{
|
||||
// Enable the feature set and make sure only its features are enabled
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, k_TestFeatureSetId, true);
|
||||
AssertOnlyFeatures(BuildTargetGroup.Standalone, new string[] { MicrosoftHandInteraction.featureId }, FeatureEnabled);
|
||||
|
||||
// Disable the feature set an make sure its features are disabled
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, k_TestFeatureSetId, false);
|
||||
AssertAllFeatures(BuildTargetGroup.Standalone, FeatureDisabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisableSharedFeaturesLeaveSharedFeaturesEnabled()
|
||||
{
|
||||
// Ensable all WSA feature sets and make sure only the WSA feature set features are enabled
|
||||
EnableFeatureSets(BuildTargetGroup.WSA, enabled: true);
|
||||
|
||||
AssertOnlyFeatures(BuildTargetGroup.WSA, new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
EyeGazeInteraction.featureId,
|
||||
}, FeatureEnabled);
|
||||
|
||||
// Disable the feature seth with both features set as required
|
||||
EnableFeatureSet(BuildTargetGroup.WSA, k_TestFeatureSetIdTwo, enabled: false);
|
||||
AssertOnlyFeatures(BuildTargetGroup.WSA, new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
}, FeatureEnabled);
|
||||
|
||||
// Disable all WSA feature sets and make sure all features are disabled
|
||||
EnableFeatureSets(BuildTargetGroup.WSA, enabled: false);
|
||||
AssertAllFeatures(BuildTargetGroup.WSA, FeatureDisabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisableSharedFeaturesLeaveOthersFeaturesEnabled()
|
||||
{
|
||||
string[] allFeatureIds = new string[]
|
||||
{
|
||||
MicrosoftHandInteraction.featureId,
|
||||
EyeGazeInteraction.featureId,
|
||||
MicrosoftMotionControllerProfile.featureId,
|
||||
};
|
||||
|
||||
string[] otherFeatureIds = new string[]
|
||||
{
|
||||
MicrosoftMotionControllerProfile.featureId,
|
||||
};
|
||||
|
||||
EnableFeatureInfos(BuildTargetGroup.WSA, otherFeatureIds, true);
|
||||
|
||||
// Enable the second feature set and ensure that only features in the `all` list are enabled
|
||||
var featureSetToEnable = GetFeatureSetInfoWithId(BuildTargetGroup.WSA, k_TestFeatureSetIdTwo);
|
||||
EnableFeatureSet(BuildTargetGroup.WSA, featureSetToEnable.featureSetId, true);
|
||||
AssertOnlyFeatures(BuildTargetGroup.WSA, allFeatureIds, FeatureEnabled);
|
||||
|
||||
// Disable the second feature set and ensure only features in the `others` list are enabled
|
||||
var featureSetToDisable = GetFeatureSetInfoWithId(BuildTargetGroup.WSA, k_TestFeatureSetIdTwo);
|
||||
Assert.IsNotNull(featureSetToDisable);
|
||||
EnableFeatureSet(BuildTargetGroup.WSA, featureSetToDisable.featureSetId, enabled: false);
|
||||
AssertOnlyFeatures(BuildTargetGroup.WSA, otherFeatureIds, FeatureEnabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EnablingFeatureSetEnabledDefaultFeatures()
|
||||
{
|
||||
var foundFeatureSet = GetFeatureSetInfoWithId(BuildTargetGroup.Standalone, k_TestFeatureSetIdFour);
|
||||
Assert.IsNotNull(foundFeatureSet);
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, true);
|
||||
|
||||
// Ensure that only the non-optional features are enabled
|
||||
AssertOnlyFeatures(BuildTargetGroup.Standalone, foundFeatureSet.featureIds, (f) => f.Feature.enabled == !FeatureIsOptional(foundFeatureSet, f));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EnablingFeatureSetLeavesOptionFeaturesEnabled()
|
||||
{
|
||||
// Enable the feature set
|
||||
var foundFeatureSet = GetFeatureSetInfoWithId(BuildTargetGroup.Standalone, k_TestFeatureSetIdFour);
|
||||
Assert.IsNotNull(foundFeatureSet);
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, true);
|
||||
|
||||
// Ensure the Optional features are all disabled
|
||||
AssertAllFeatures(BuildTargetGroup.Standalone, (f) => !FeatureIsOptional(foundFeatureSet, f) || !f.Feature.enabled);
|
||||
|
||||
// Disable the feature set and ensure the optional features are disabled
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, false);
|
||||
AssertAllFeatures(BuildTargetGroup.Standalone, (f) => !FeatureIsOptional(foundFeatureSet, f) || !f.Feature.enabled);
|
||||
|
||||
// Enable the optional features and the feature set and ensure the optional features are still enabled
|
||||
EnableFeatureInfos(BuildTargetGroup.Standalone, true, (f) => FeatureIsOptional(foundFeatureSet, f));
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, enabled: true);
|
||||
AssertAllFeatures(BuildTargetGroup.Standalone, (f) => !FeatureIsOptional(foundFeatureSet, f) || f.Feature.enabled);
|
||||
|
||||
// Enable the feature set again and make sure the optional features are still enabled
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, enabled: true);
|
||||
AssertAllFeatures(BuildTargetGroup.Standalone, (f) => !FeatureIsOptional(foundFeatureSet, f) || f.Feature.enabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisablingFeatureSetLeavesDefaultFeaturesEnabled()
|
||||
{
|
||||
var foundFeatureSet = GetFeatureSetInfoWithId(BuildTargetGroup.Standalone, k_TestFeatureSetIdFour);
|
||||
Assert.IsNotNull(foundFeatureSet);
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, true);
|
||||
|
||||
// Ensure that the only enabled features are the non optional features
|
||||
AssertAllFeatures(BuildTargetGroup.Standalone, foundFeatureSet.featureIds, (f) => f.Feature.enabled == !FeatureIsOptional(foundFeatureSet, f));
|
||||
|
||||
// Disabling the feature set should disable the required components but not the default ones
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, enabled: false);
|
||||
AssertAllFeatures(BuildTargetGroup.Standalone, foundFeatureSet.requiredFeatureIds, FeatureDisabled);
|
||||
AssertAllFeatures(BuildTargetGroup.Standalone, foundFeatureSet.defaultFeatureIds, FeatureEnabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisablingFeatureSetLeavesDisabledDefaultFeaturesDisabled()
|
||||
{
|
||||
var buildTargetGroup = BuildTargetGroup.Standalone;
|
||||
var foundFeatureSet = GetFeatureSetInfoWithId(buildTargetGroup, k_TestFeatureSetIdFour);
|
||||
Assert.IsNotNull(foundFeatureSet);
|
||||
|
||||
EnableFeatureSet(buildTargetGroup, foundFeatureSet.featureSetId, enabled: true);
|
||||
|
||||
// Ensure that only the non optional features are enabled
|
||||
AssertOnlyFeatures(buildTargetGroup, foundFeatureSet.featureIds, (f) => f.Feature.enabled == !FeatureIsOptional(foundFeatureSet, f));
|
||||
|
||||
// Disable all features in the default feature list
|
||||
EnableFeatureInfos(buildTargetGroup, foundFeatureSet.defaultFeatureIds, enable: false);
|
||||
AssertAllFeatures(buildTargetGroup, foundFeatureSet.defaultFeatureIds, FeatureDisabled);
|
||||
|
||||
// Ensure that all features in the required list are enabled and that all features in the default features list are disabled
|
||||
AssertAllFeatures(buildTargetGroup, foundFeatureSet.requiredFeatureIds, FeatureEnabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanNotChangeEnabledStateOfRequiredFeature()
|
||||
{
|
||||
OpenXRFeatureSetManager.activeBuildTarget = BuildTargetGroup.Standalone;
|
||||
|
||||
var foundFeatureSet = GetFeatureSetInfoWithId(BuildTargetGroup.Standalone, k_TestFeatureSetIdFour);
|
||||
Assert.IsNotNull(foundFeatureSet);
|
||||
|
||||
var featureInfos = GetFeatureInfos(BuildTargetGroup.Standalone, foundFeatureSet.requiredFeatureIds);
|
||||
foreach (var featureInfo in featureInfos)
|
||||
{
|
||||
AssertFeatureEnabled(featureInfo, false);
|
||||
featureInfo.Feature.enabled = true;
|
||||
AssertFeatureEnabled(featureInfo, true);
|
||||
featureInfo.Feature.enabled = false;
|
||||
AssertFeatureEnabled(featureInfo, false);
|
||||
}
|
||||
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, enabled: true);
|
||||
|
||||
OpenXRFeature.canSetFeatureDisabled = OpenXRFeatureSetManager.CanFeatureBeDisabled;
|
||||
|
||||
foreach (var featureInfo in featureInfos)
|
||||
{
|
||||
AssertFeatureEnabled(featureInfo, true);
|
||||
featureInfo.Feature.enabled = false;
|
||||
AssertFeatureEnabled(featureInfo, true);
|
||||
}
|
||||
|
||||
EnableFeatureSet(BuildTargetGroup.Standalone, foundFeatureSet.featureSetId, enabled: false);
|
||||
|
||||
foreach (var featureInfo in featureInfos)
|
||||
{
|
||||
AssertFeatureEnabled(featureInfo, false);
|
||||
featureInfo.Feature.enabled = true;
|
||||
AssertFeatureEnabled(featureInfo, true);
|
||||
featureInfo.Feature.enabled = false;
|
||||
AssertFeatureEnabled(featureInfo, false);
|
||||
}
|
||||
|
||||
OpenXRFeatureSetManager.activeBuildTarget = BuildTargetGroup.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 328562bda27130c4a853afe94025c8a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
122
Packages/com.unity.xr.openxr/Tests/Editor/FeatureTests.cs
Normal file
122
Packages/com.unity.xr.openxr/Tests/Editor/FeatureTests.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR.Features.Mock;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using static UnityEditor.XR.OpenXR.Tests.OpenXREditorTestHelpers;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class FeatureTests : OpenXRLoaderSetup
|
||||
{
|
||||
[Test]
|
||||
public void EnableFeatures()
|
||||
{
|
||||
var featureInfos = GetFeatureInfos(BuildTargetGroup.Standalone);
|
||||
featureInfos.SingleOrDefault(ext => ext.Attribute.UiName == "Mock Runtime").Feature.enabled = true;
|
||||
Assert.IsTrue(MockRuntime.Instance.enabled);
|
||||
|
||||
featureInfos.SingleOrDefault(ext => ext.Attribute.UiName == "Mock Runtime").Feature.enabled = false;
|
||||
Assert.IsFalse(MockRuntime.Instance.enabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckDefaultValues()
|
||||
{
|
||||
var featureInfos = GetFeatureInfos(BuildTargetGroup.Standalone);
|
||||
var mockExtInfo = featureInfos.SingleOrDefault(ext => ext.Attribute.UiName == "Mock Runtime");
|
||||
|
||||
Assert.AreEqual(mockExtInfo.Attribute.UiName, mockExtInfo.Feature.nameUi);
|
||||
Assert.AreEqual(mockExtInfo.Attribute.Version, mockExtInfo.Feature.version);
|
||||
Assert.AreEqual(mockExtInfo.Attribute.OpenxrExtensionStrings, mockExtInfo.Feature.openxrExtensionStrings);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ValidationError()
|
||||
{
|
||||
bool errorFixed = false;
|
||||
|
||||
// Set up a validation check ...
|
||||
MockRuntime.Instance.TestCallback = (s, o) =>
|
||||
{
|
||||
if (s == "GetValidationChecks")
|
||||
{
|
||||
var validationChecks = o as List<OpenXRFeature.ValidationRule>;
|
||||
validationChecks?.Add(new OpenXRFeature.ValidationRule
|
||||
{
|
||||
message = "Mock Validation Fail",
|
||||
checkPredicate = () => errorFixed,
|
||||
fixIt = () => errorFixed = true,
|
||||
error = true
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// Try to build the player ...
|
||||
var report = zBuildHookTests.BuildMockPlayer();
|
||||
|
||||
// It will fail because of the above validation issue ...
|
||||
Assert.AreEqual(BuildResult.Failed, report.summary.result);
|
||||
|
||||
// There's one validation issue ...
|
||||
var validationIssues = new List<OpenXRFeature.ValidationRule>();
|
||||
OpenXRProjectValidation.GetCurrentValidationIssues(validationIssues, BuildTargetGroup.Standalone);
|
||||
Assert.AreEqual(1, validationIssues.Count);
|
||||
|
||||
// Fix it ...
|
||||
Assert.IsFalse(errorFixed);
|
||||
validationIssues[0].fixIt.Invoke();
|
||||
Assert.IsTrue(errorFixed);
|
||||
|
||||
// Now there's zero validation issues ...
|
||||
OpenXRProjectValidation.GetCurrentValidationIssues(validationIssues, BuildTargetGroup.Standalone);
|
||||
Assert.AreEqual(0, validationIssues.Count);
|
||||
|
||||
// Close the validation window ...
|
||||
OpenXRProjectValidationRulesSetup.CloseWindow();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFeatureByFeatureId()
|
||||
{
|
||||
var feature = FeatureHelpers.GetFeatureWithIdForActiveBuildTarget(MockRuntime.featureId);
|
||||
Assert.IsNotNull(feature);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFeatureByUnknownFeatureIdReturnsNull()
|
||||
{
|
||||
var feature = FeatureHelpers.GetFeatureWithIdForActiveBuildTarget("some.unknown.feature.id");
|
||||
Assert.IsNull(feature);
|
||||
|
||||
feature = FeatureHelpers.GetFeatureWithIdForActiveBuildTarget("");
|
||||
Assert.IsNull(feature);
|
||||
|
||||
feature = FeatureHelpers.GetFeatureWithIdForActiveBuildTarget(null);
|
||||
Assert.IsNull(feature);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetFeaturesWithIdsReturnsFeatures()
|
||||
{
|
||||
var featureIds = new string[] { MockRuntime.featureId, EyeGazeInteraction.featureId };
|
||||
var features = FeatureHelpers.GetFeaturesWithIdsForActiveBuildTarget(featureIds);
|
||||
Assert.IsNotNull(features);
|
||||
Assert.IsTrue(features.Length == 2);
|
||||
|
||||
var expectedTypes = new Type[] { typeof(MockRuntime), typeof(EyeGazeInteraction) };
|
||||
foreach (var feature in features)
|
||||
{
|
||||
Assert.IsTrue(Array.IndexOf(expectedTypes, feature.GetType()) > -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a788d71a20869d4db1291a18e647426
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bcf50ca7a335ea40b37e3bcf05eea52
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Mock;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class OpenXRCallbackTests : OpenXRLoaderSetup
|
||||
{
|
||||
[Test]
|
||||
public void InstanceCreated()
|
||||
{
|
||||
bool instanceCreated = false;
|
||||
MockRuntime.Instance.TestCallback = (methodName, param) =>
|
||||
{
|
||||
if (methodName == nameof(OpenXRFeature.OnInstanceCreate))
|
||||
{
|
||||
instanceCreated = true;
|
||||
Assert.AreEqual(10, (ulong)param);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
AddExtension(MockRuntime.XR_UNITY_mock_test);
|
||||
|
||||
base.InitializeAndStart();
|
||||
|
||||
Assert.IsTrue(instanceCreated);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SessionCreated()
|
||||
{
|
||||
bool sessionCreated = false;
|
||||
MockRuntime.Instance.TestCallback = (methodName, param) =>
|
||||
{
|
||||
if (methodName == nameof(OpenXRFeature.OnSessionCreate))
|
||||
{
|
||||
sessionCreated = true;
|
||||
Assert.AreEqual(3, (ulong)param);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
base.InitializeAndStart();
|
||||
|
||||
Assert.IsTrue(sessionCreated);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8dc9dc15a0724a46ba08d4aecabca976
|
||||
timeCreated: 1586986782
|
||||
@@ -0,0 +1,62 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.Scripting;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
#if false // Tests are temporarily disabled due to an issue with [BeforeTest] being called twice during a domain reload
|
||||
|
||||
/// <summary>
|
||||
/// Tests domain reloads within OpenXR. Note that his class was named with two z's in front
|
||||
/// because the domain reloads during this test were causing other tests to fail that ran after it.
|
||||
/// </summary>
|
||||
internal class zzOpenXRDomainReloadTests : OpenXRLoaderSetup
|
||||
{
|
||||
[UnityTest]
|
||||
public IEnumerator AfterInitialize()
|
||||
{
|
||||
MockRuntimeFeature.Instance.TestCallback = (methodName, param) => true;
|
||||
|
||||
Assert.IsNull(OpenXRLoaderBase.Instance);
|
||||
|
||||
base.InitializeAndStart();
|
||||
|
||||
// Perform a domain reload and wait for it to complete
|
||||
EditorUtility.RequestScriptReload();
|
||||
yield return new WaitForDomainReload();
|
||||
|
||||
Assert.IsNotNull(OpenXRLoaderBase.Instance);
|
||||
|
||||
base.StopAndShutdown();
|
||||
|
||||
Assert.IsNull(OpenXRLoaderBase.Instance);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator BeforeInitialize()
|
||||
{
|
||||
MockRuntimeFeature.Instance.TestCallback = (methodName, param) => true;
|
||||
|
||||
// Perform a domain reload and wait for it to complete
|
||||
EditorUtility.RequestScriptReload();
|
||||
yield return new WaitForDomainReload();
|
||||
|
||||
base.InitializeAndStart();
|
||||
base.StopAndShutdown();
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 742a28a82ea69ef4fba68040fee09aac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,230 @@
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using static UnityEditor.XR.OpenXR.Features.OpenXRFeatureSetManager;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal static class OpenXREditorTestHelpers
|
||||
{
|
||||
public delegate bool FeatureInfoPredicate(FeatureHelpersInternal.FeatureInfo featureInfo);
|
||||
|
||||
public static bool FeatureEnabled(FeatureHelpersInternal.FeatureInfo featureInfo) => featureInfo.Feature.enabled;
|
||||
public static bool FeatureDisabled(FeatureHelpersInternal.FeatureInfo featureInfo) => !featureInfo.Feature.enabled;
|
||||
|
||||
private static Dictionary<BuildTargetGroup, FeatureHelpersInternal.FeatureInfo[]> s_FeatureInfos;
|
||||
|
||||
private static BuildTargetGroup[] s_BuildTargetGroups =
|
||||
((BuildTargetGroup[])Enum.GetValues(typeof(BuildTargetGroup))).Distinct().ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Return the distinct list of build target groups to test
|
||||
/// </summary>
|
||||
public static BuildTargetGroup[] GetBuildTargetGroups() => s_BuildTargetGroups;
|
||||
|
||||
/// <summary>
|
||||
/// Clear the FeatureInfo cache
|
||||
/// </summary>
|
||||
public static void ClearFeatureInfos()
|
||||
{
|
||||
s_FeatureInfos = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to retrieve the cached FeatureInfos for a given build target group
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build target group</param>
|
||||
/// <returns>Array of FeatureInfos for the build target group</returns>
|
||||
public static FeatureHelpersInternal.FeatureInfo[] GetFeatureInfos(BuildTargetGroup buildTargetGroup)
|
||||
{
|
||||
if (null == s_FeatureInfos)
|
||||
s_FeatureInfos = new Dictionary<BuildTargetGroup, FeatureHelpersInternal.FeatureInfo[]>();
|
||||
|
||||
if (!s_FeatureInfos.TryGetValue(buildTargetGroup, out var featureInfos))
|
||||
{
|
||||
featureInfos = FeatureHelpersInternal.GetAllFeatureInfo(buildTargetGroup).Features.ToArray();
|
||||
s_FeatureInfos[buildTargetGroup] = featureInfos;
|
||||
}
|
||||
|
||||
return featureInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to retrieve a subset of FeatureInfos in <paramref name="buildTargetGroup"/>.
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build target group</param>
|
||||
/// <param name="featureIds">Specific feature identifiers to retrieve</param>
|
||||
/// <returns>Array of FeatureInfos matching request</returns>
|
||||
public static FeatureHelpersInternal.FeatureInfo[] GetFeatureInfos(BuildTargetGroup buildTargetGroup, string[] featureIds)
|
||||
{
|
||||
return GetFeatureInfos(buildTargetGroup).Where(f => featureIds.Contains(f.Attribute.FeatureId)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable a feature set
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build target group containing feature set</param>
|
||||
/// <param name="featureSetId">Identifier of feature</param>
|
||||
/// <param name="enabled">True to enable, false to disable</param>
|
||||
/// <param name="changed">True if the FeatureSet enabled state should be considered changed</param>
|
||||
/// <param name="commit">True if the FeatureSet enabled state should be automatically commmitted with `SetFeaturesFromEnabledFeatureSets`</param>
|
||||
public static void EnableFeatureSet(BuildTargetGroup buildTargetGroup, string featureSetId, bool enabled = true, bool changed = true, bool commit = true)
|
||||
{
|
||||
var featureSetInfo = GetFeatureSetInfoWithId(buildTargetGroup, featureSetId);
|
||||
Assert.IsNotNull(featureSetInfo, $"FeatureSetInfo '{featureSetId}' not found ");
|
||||
|
||||
featureSetInfo.isEnabled = enabled;
|
||||
featureSetInfo.wasEnabled = changed ? !enabled : enabled;
|
||||
|
||||
if (commit)
|
||||
SetFeaturesFromEnabledFeatureSets(buildTargetGroup);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable/Disable all feature sets for <paramref name="buildTargetGroup"/>
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build Target Group</param>
|
||||
/// <param name="enabled">Enabled state</param>
|
||||
/// <param name="changed">True if the feature set should be marked as changed, false if not</param>
|
||||
public static void EnableFeatureSets(BuildTargetGroup buildTargetGroup, bool enabled, bool changed = true, bool commit = true)
|
||||
{
|
||||
foreach (var featureSetInfo in FeatureSetInfosForBuildTarget(buildTargetGroup))
|
||||
{
|
||||
featureSetInfo.isEnabled = enabled;
|
||||
featureSetInfo.wasEnabled = changed ? !enabled : enabled;
|
||||
}
|
||||
|
||||
if (commit)
|
||||
SetFeaturesFromEnabledFeatureSets(buildTargetGroup);
|
||||
}
|
||||
|
||||
public static void EnableFeatureInfos(BuildTargetGroup buildTargetGroup, string[] featureIds, bool enable, FeatureInfoPredicate predicate = null)
|
||||
{
|
||||
foreach (var featureInfo in GetFeatureInfos(buildTargetGroup, featureIds))
|
||||
{
|
||||
if (null == predicate || predicate(featureInfo))
|
||||
featureInfo.Feature.enabled = enable;
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableFeatureInfos(BuildTargetGroup buildTargetGroup, bool enable, FeatureInfoPredicate predicate = null)
|
||||
{
|
||||
foreach (var featureInfo in GetFeatureInfos(buildTargetGroup))
|
||||
{
|
||||
if (null == predicate || predicate(featureInfo))
|
||||
featureInfo.Feature.enabled = enable;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a comma separated list of features that pass the <paramref name="check"/> within <paramref name="featureInfos"/>
|
||||
/// </summary>
|
||||
/// <param name="featureInfos">Feature infos</param>
|
||||
/// <param name="check">Delegate used to check status</param>
|
||||
/// <param name="exclude">Optional list of feature identifiers exclude</param>
|
||||
/// <returns>Comma separated list of features</returns>
|
||||
public static string FeaturesToString(FeatureHelpersInternal.FeatureInfo[] featureInfos, FeatureInfoPredicate check, string[] exclude = null)
|
||||
{
|
||||
return string.Join(",", featureInfos
|
||||
.Where(f => (exclude == null || !exclude.Contains(f.Attribute.FeatureId)) && check(f))
|
||||
.Select(f => f.Attribute.FeatureId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a comma separated list of features from <paramref name="featureIds"/> in <paramref name="buildTargetGroup"/> that pass the <paramref name="check"/>
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build Target Group</param>
|
||||
/// <param name="featureIds">Feature ids to include</param>
|
||||
/// <param name="check">Delegate used to check status</param>
|
||||
/// <returns>Comma separated list of features</returns>
|
||||
public static string FeaturesToString(BuildTargetGroup buildTargetGroup, string[] featureIds, FeatureInfoPredicate check)
|
||||
{
|
||||
return FeaturesToString(GetFeatureInfos(buildTargetGroup).Where(f => featureIds.Contains(f.Attribute.FeatureId)).ToArray(), check);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a comma separated list of features identifier that pass the <paramref name="check"/> within <paramref name="buildTargetGroup"/>
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build Target Group</param>
|
||||
/// <param name="check">Delegate used to check status</param>
|
||||
/// <param name="exclude">Optional list of feature identifiers to exclude from the list</param>
|
||||
/// <returns>Comma separated list of features</returns>
|
||||
public static string FeaturesToString(BuildTargetGroup buildTargetGroup, FeatureInfoPredicate check, string[] exclude = null)
|
||||
{
|
||||
return FeaturesToString(GetFeatureInfos(buildTargetGroup), check, exclude: exclude);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if all features for the <paramref name="buildTargetGroup"/> pass the <paramref name="check"/>.
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build Target Group</param>
|
||||
/// <param name="check">Delegate used to check status</param>
|
||||
/// <returns>True if the check passes, false if not</returns>
|
||||
public static bool CheckAllFeatures(BuildTargetGroup buildTargetGroup, FeatureInfoPredicate check)
|
||||
{
|
||||
return GetFeatureInfos(buildTargetGroup).All(f => check(f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that all features in <paramref name="featureIds"/> in <paramref name="buildTargetGroup"/> match the pass the <paramref name="check"/>.
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build target group</param>
|
||||
/// <param name="featureIds">Features to check</param>
|
||||
/// <param name="check">Delegate used to check status</param>
|
||||
/// <returns>True if the check passes, false if not</returns>
|
||||
public static bool CheckAllFeatures(BuildTargetGroup buildTargetGroup, string[] featureIds, FeatureInfoPredicate check)
|
||||
{
|
||||
return GetFeatureInfos(buildTargetGroup).All(f => !featureIds.Contains(f.Attribute.FeatureId) || check(f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that only features in <paramref name="featureIds"/> for <paramref name="buildTargetGroup"/> pass the <paramref name="check"/>.
|
||||
/// </summary>
|
||||
/// <param name="buildTargetGroup">Build target group</param>
|
||||
/// <param name="featureIds">Features to check</param>
|
||||
/// <param name="check">Delegate used to check a FeatureInfo</param>
|
||||
/// <returns>True if the check passes, false if not</returns>
|
||||
public static bool CheckOnlyFeatures(BuildTargetGroup buildTargetGroup, string[] featureIds, FeatureInfoPredicate check)
|
||||
{
|
||||
return GetFeatureInfos(buildTargetGroup).All(f => featureIds.Contains(f.Attribute.FeatureId) == check(f));
|
||||
}
|
||||
|
||||
private static string AssertFeaturesMessage(string features) =>
|
||||
$"The following features failed the check: {features}";
|
||||
|
||||
public static void AssertOnlyFeatures(BuildTargetGroup buildTargetGroup, string[] featureIds, FeatureInfoPredicate check)
|
||||
{
|
||||
Assert.IsTrue(
|
||||
CheckOnlyFeatures(buildTargetGroup, featureIds, check),
|
||||
AssertFeaturesMessage(FeaturesToString(buildTargetGroup, featureIds, (f) => !check(f))));
|
||||
}
|
||||
|
||||
public static void AssertAllFeatures(BuildTargetGroup buildTargetGroup, string[] featureIds, FeatureInfoPredicate check)
|
||||
{
|
||||
Assert.IsTrue(
|
||||
CheckAllFeatures(buildTargetGroup, featureIds, check),
|
||||
AssertFeaturesMessage(FeaturesToString(buildTargetGroup, featureIds, (f) => !check(f))));
|
||||
}
|
||||
|
||||
public static void AssertAllFeatures(BuildTargetGroup buildTargetGroup, FeatureInfoPredicate check)
|
||||
{
|
||||
Assert.IsTrue(
|
||||
CheckAllFeatures(buildTargetGroup, check),
|
||||
AssertFeaturesMessage(FeaturesToString(buildTargetGroup, (f) => !check(f))));
|
||||
}
|
||||
|
||||
public static void AssertFeatureEnabled(FeatureHelpersInternal.FeatureInfo featureInfo, bool enabled = true)
|
||||
{
|
||||
Assert.IsTrue(featureInfo.Feature.enabled == enabled, $"{featureInfo.Attribute.FeatureId} should be {(enabled ? "enabled" : "disabled")}");
|
||||
}
|
||||
|
||||
public static bool FeatureIsOptional(FeatureSetInfo featureSet, FeatureHelpersInternal.FeatureInfo feature)
|
||||
{
|
||||
return Array.IndexOf(featureSet.featureIds, feature.Attribute.FeatureId) > -1 &&
|
||||
(featureSet.requiredFeatureIds == null || Array.IndexOf(featureSet.requiredFeatureIds, feature.Attribute.FeatureId) == -1) &&
|
||||
(featureSet.defaultFeatureIds == null || Array.IndexOf(featureSet.defaultFeatureIds, feature.Attribute.FeatureId) == -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f87eee2b71c3bf24aa0e63794ac22ae5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class OpenXREditorTests
|
||||
{
|
||||
[Test]
|
||||
public void DocumentationVersion()
|
||||
{
|
||||
var version = PackageManager.PackageInfo.FindForAssembly(typeof(OpenXREditorTests).Assembly)?.version;
|
||||
var majorminor = "@" + OpenXRFeatureAttribute.k_PackageVersionRegex.Match(version).Groups[1].Value + "/";
|
||||
UnityEngine.Debug.Log(typeof(KHRSimpleControllerProfile).GetCustomAttribute<OpenXRFeatureAttribute>().InternalDocumentationLink);
|
||||
Assert.IsTrue(typeof(KHRSimpleControllerProfile).GetCustomAttribute<OpenXRFeatureAttribute>().InternalDocumentationLink.Contains(majorminor));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PluginVersion()
|
||||
{
|
||||
var version = PackageManager.PackageInfo.FindForAssembly(typeof(OpenXREditorTests).Assembly)?.version;
|
||||
System.Text.RegularExpressions.Regex ReleaseVersion = new System.Text.RegularExpressions.Regex(@"^(\d+\.\d+\.\d+)$");
|
||||
//check for release build provider version number matches package version
|
||||
if (ReleaseVersion.IsMatch(version))
|
||||
{
|
||||
var tag = OpenXRRuntime.pluginVersion;
|
||||
Assert.AreEqual(0, String.Compare(version, tag), "Tag in github must match the package version number.");
|
||||
return;
|
||||
}
|
||||
//check for non-release build package version number supposed to be x.x.x-pre.x(pre-release) or x.x.x-exp.x(experimental)
|
||||
System.Text.RegularExpressions.Regex PreviewVersion = new System.Text.RegularExpressions.Regex(@"^(\d+\.\d+\.\d+\-\w+\.\d+)$");
|
||||
Assert.IsTrue(PreviewVersion.IsMatch(version), "Wrong package version format! Non-release branch should follow x.x.x-pre.x(pre-release) or x.x.x-exp.x(experimental)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c99482b3559f1f47babd8d8fec8a820
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class OpenXRInputEditorTests : OpenXRInputTestsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests whether or not the device layout for an interaction feature is registered/unregistered
|
||||
/// when the feature is enabled/disabled
|
||||
/// </summary>
|
||||
#if !INPUT_SYSTEM_BINDING_VALIDATOR
|
||||
[Test]
|
||||
public void DeviceLayoutRegistration([ValueSource(nameof(s_InteractionFeatureLayouts))] (Type featureType, Type layoutType, string layoutNameOverride) interactionFeature)
|
||||
{
|
||||
var layoutName = interactionFeature.layoutNameOverride ?? interactionFeature.layoutType.Name;
|
||||
|
||||
// Make sure the layout is not registered as it would give the test a false positive
|
||||
InputSystem.RemoveLayout(layoutName);
|
||||
Assert.IsFalse(IsLayoutRegistered(layoutName), "Layout is still registered, test will give a false positive");
|
||||
|
||||
// Enabling the feature should register the layout
|
||||
EnableFeature(interactionFeature.featureType);
|
||||
Assert.IsTrue(IsLayoutRegistered(layoutName), "Layout was not registered by enabling the feature");
|
||||
|
||||
// When an interaction feature is disabled its layout should be disable as well
|
||||
EnableFeature(interactionFeature.featureType, false);
|
||||
Assert.IsFalse(IsLayoutRegistered(layoutName), "Layout was not unregistered by the interaction feature");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that interaction features enabled in multiple build targets properly registers and unregisters
|
||||
/// the device layout depending on whether the feature is enabled in at least one build target.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void InteractionFeatureLayoutRegistration()
|
||||
{
|
||||
var packageSettings = OpenXRSettings.GetPackageSettings();
|
||||
Assert.IsNotNull(packageSettings);
|
||||
|
||||
// Ignore the test if there is not more than 1 build target.
|
||||
var features = packageSettings.GetFeatures<OculusTouchControllerProfile>().Select(f => f.feature).ToArray();
|
||||
if (features.Length < 2)
|
||||
return;
|
||||
|
||||
// Disable all of the oculus interaction features
|
||||
foreach (var feature in features)
|
||||
{
|
||||
feature.enabled = false;
|
||||
}
|
||||
|
||||
// Make sure the oculus device layout is not registered
|
||||
NUnit.Framework.Assert.Throws(typeof(ArgumentException), () => UnityEngine.InputSystem.InputSystem.LoadLayout<OculusTouchControllerProfile.OculusTouchController>());
|
||||
|
||||
// Enable one of the features and make sure the layout is registered
|
||||
features[0].enabled = true;
|
||||
NUnit.Framework.Assert.DoesNotThrow(() => UnityEngine.InputSystem.InputSystem.LoadLayout<OculusTouchControllerProfile.OculusTouchController>());
|
||||
NUnit.Framework.Assert.DoesNotThrow(() => UnityEngine.InputSystem.InputSystem.LoadLayout<OculusTouchControllerProfile.OculusTouchController>());
|
||||
|
||||
// Enable a second feature and make sure the layout is still enabled
|
||||
features[1].enabled = true;
|
||||
NUnit.Framework.Assert.DoesNotThrow(() => UnityEngine.InputSystem.InputSystem.LoadLayout<OculusTouchControllerProfile.OculusTouchController>());
|
||||
|
||||
// Disable the first feature and make sure the layout is still enabled
|
||||
features[0].enabled = false;
|
||||
NUnit.Framework.Assert.DoesNotThrow(() => UnityEngine.InputSystem.InputSystem.LoadLayout<OculusTouchControllerProfile.OculusTouchController>());
|
||||
|
||||
// Disable the second feature and make sure the layout is no longer
|
||||
features[1].enabled = false;
|
||||
NUnit.Framework.Assert.Throws(typeof(ArgumentException), () => UnityEngine.InputSystem.InputSystem.LoadLayout<OculusTouchControllerProfile.OculusTouchController>());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee1a4eb1841c4a40a7e4a76be579ca3e
|
||||
timeCreated: 1622132012
|
||||
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class OpenXRRuntimeSelectorTests : OpenXRInputTestsBase
|
||||
{
|
||||
[Test]
|
||||
public void NoAvailableRuntimesTest()
|
||||
{
|
||||
List<OpenXRRuntimeSelector.RuntimeDetector> detectorList = OpenXRRuntimeSelector.GenerateRuntimeDetectorList();
|
||||
Assert.IsTrue(detectorList.Count > 0);
|
||||
Assert.IsTrue(detectorList[0] is OpenXRRuntimeSelector.SystemDefault, "First choice should always be SystemDefault");
|
||||
Assert.IsTrue(detectorList[detectorList.Count - 1] is OpenXRRuntimeSelector.OtherRuntime, "Last choice should always be Other");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuiltInRuntimesAsAvailableRuntimesTest()
|
||||
{
|
||||
// Simulate what happens if the AvailableRuntimes registry key is empty.
|
||||
// WindowsMR, SteamVR, and Oculus should all be added to the list.
|
||||
Dictionary<string, int> runtimePathToValue = new Dictionary<string, int>();
|
||||
List<OpenXRRuntimeSelector.RuntimeDetector> detectorList = OpenXRRuntimeSelector.GenerateRuntimeDetectorList(runtimePathToValue);
|
||||
Assert.IsTrue(detectorList.Count > 0);
|
||||
Assert.IsTrue(detectorList[0] is OpenXRRuntimeSelector.SystemDefault);
|
||||
Assert.IsTrue(detectorList[detectorList.Count - 1] is OpenXRRuntimeSelector.OtherRuntime);
|
||||
|
||||
bool foundWindowsMRDetector = false;
|
||||
bool foundSteamVRDetector = false;
|
||||
bool foundOculusDetector = false;
|
||||
foreach (var detector in detectorList)
|
||||
{
|
||||
foundWindowsMRDetector |= detector is OpenXRRuntimeSelector.WindowsMRDetector;
|
||||
foundSteamVRDetector |= detector is OpenXRRuntimeSelector.SteamVRDetector;
|
||||
foundOculusDetector |= detector is OpenXRRuntimeSelector.OculusDetector;
|
||||
}
|
||||
|
||||
Assert.IsTrue(foundWindowsMRDetector);
|
||||
Assert.IsTrue(foundSteamVRDetector);
|
||||
Assert.IsTrue(foundOculusDetector);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DiscoveredAvailableRuntimesTest()
|
||||
{
|
||||
OpenXRRuntimeSelector.WindowsMRDetector windowsMRDetector = new OpenXRRuntimeSelector.WindowsMRDetector();
|
||||
OpenXRRuntimeSelector.SteamVRDetector steamVRDetector = new OpenXRRuntimeSelector.SteamVRDetector();
|
||||
OpenXRRuntimeSelector.OculusDetector oculusDetector = new OpenXRRuntimeSelector.OculusDetector();
|
||||
string enabledRuntime = "enabledRuntime";
|
||||
string disabledRuntime = "disabledRuntime";
|
||||
|
||||
Dictionary<string, int> runtimePathToValue = new Dictionary<string, int>()
|
||||
{
|
||||
{ windowsMRDetector.jsonPath, 0},
|
||||
{ steamVRDetector.jsonPath, 1},
|
||||
{ enabledRuntime, 0 },
|
||||
{ disabledRuntime, 1 }
|
||||
};
|
||||
|
||||
List<OpenXRRuntimeSelector.RuntimeDetector> detectorList = OpenXRRuntimeSelector.GenerateRuntimeDetectorList(runtimePathToValue);
|
||||
Assert.IsTrue(detectorList.Count > 0);
|
||||
Assert.IsTrue(detectorList[0] is OpenXRRuntimeSelector.SystemDefault);
|
||||
Assert.IsTrue(detectorList[detectorList.Count - 1] is OpenXRRuntimeSelector.OtherRuntime);
|
||||
|
||||
HashSet<string> detectedJsons = new HashSet<string>();
|
||||
foreach (var detector in detectorList)
|
||||
{
|
||||
detectedJsons.Add(detector.jsonPath);
|
||||
}
|
||||
|
||||
Assert.IsTrue(detectedJsons.Contains(windowsMRDetector.jsonPath));
|
||||
Assert.IsFalse(detectedJsons.Contains(steamVRDetector.jsonPath));
|
||||
Assert.IsTrue(detectedJsons.Contains(oculusDetector.jsonPath));
|
||||
Assert.IsTrue(detectedJsons.Contains(enabledRuntime));
|
||||
Assert.IsFalse(detectedJsons.Contains(disabledRuntime));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSelectOtherRuntime()
|
||||
{
|
||||
// Get the OtherRuntime choice (verify that it's the last detector)
|
||||
var runtimeDetector = OpenXRRuntimeSelector.RuntimeDetectors[OpenXRRuntimeSelector.RuntimeDetectors.Count - 1];
|
||||
OpenXRRuntimeSelector.OtherRuntime otherRuntime = runtimeDetector as OpenXRRuntimeSelector.OtherRuntime;
|
||||
Assert.IsTrue(otherRuntime != null);
|
||||
|
||||
// Save data that this test will modify to restore state after the test finishes.
|
||||
string previousOtherJsonPath = otherRuntime.jsonPath;
|
||||
string previousActiveRuntime = Environment.GetEnvironmentVariable(OpenXRRuntimeSelector.RuntimeDetector.k_RuntimeEnvKey);
|
||||
string previousSelectedRuntime = Environment.GetEnvironmentVariable(OpenXRRuntimeSelector.k_SelectedRuntimeEnvKey);
|
||||
|
||||
try
|
||||
{
|
||||
// Set the other runtime value and set this as the selected runtime.
|
||||
string jsonPath = "testJsonPath";
|
||||
otherRuntime.SetOtherRuntimeJsonPath(jsonPath);
|
||||
OpenXRRuntimeSelector.SetSelectedRuntime(jsonPath);
|
||||
|
||||
// Exit Edit Mode. Active runtime and Selected runtime should have the json path.
|
||||
OpenXRRuntimeSelector.ActivateOrDeactivateRuntime(PlayModeStateChange.ExitingEditMode);
|
||||
string activeRuntime = Environment.GetEnvironmentVariable(OpenXRRuntimeSelector.RuntimeDetector.k_RuntimeEnvKey);
|
||||
string selectedRuntime = Environment.GetEnvironmentVariable(OpenXRRuntimeSelector.k_SelectedRuntimeEnvKey);
|
||||
Assert.AreEqual(activeRuntime, jsonPath);
|
||||
Assert.AreEqual(selectedRuntime, jsonPath);
|
||||
|
||||
// Simulate a refresh of the runtime detectors when entering play mode.
|
||||
// The OtherRuntime should still have the jsonPath from before.
|
||||
OpenXRRuntimeSelector.RefreshRuntimeDetectorList();
|
||||
runtimeDetector = OpenXRRuntimeSelector.RuntimeDetectors[OpenXRRuntimeSelector.RuntimeDetectors.Count - 1];
|
||||
otherRuntime = runtimeDetector as OpenXRRuntimeSelector.OtherRuntime;
|
||||
Assert.AreEqual(otherRuntime.jsonPath, jsonPath);
|
||||
|
||||
// Enter Edit Mode. Active runtime should be cleared, selected runtime should still have the json path.
|
||||
OpenXRRuntimeSelector.ActivateOrDeactivateRuntime(PlayModeStateChange.EnteredEditMode);
|
||||
activeRuntime = Environment.GetEnvironmentVariable(OpenXRRuntimeSelector.RuntimeDetector.k_RuntimeEnvKey);
|
||||
selectedRuntime = Environment.GetEnvironmentVariable(OpenXRRuntimeSelector.k_SelectedRuntimeEnvKey);
|
||||
Assert.AreNotEqual(activeRuntime, jsonPath);
|
||||
Assert.AreEqual(selectedRuntime, jsonPath);
|
||||
|
||||
// Refresh again. OtherRuntime and selected runtime should still have the json path.
|
||||
OpenXRRuntimeSelector.RefreshRuntimeDetectorList();
|
||||
runtimeDetector = OpenXRRuntimeSelector.RuntimeDetectors[OpenXRRuntimeSelector.RuntimeDetectors.Count - 1];
|
||||
otherRuntime = runtimeDetector as OpenXRRuntimeSelector.OtherRuntime;
|
||||
Assert.AreEqual(otherRuntime.jsonPath, jsonPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
otherRuntime.SetOtherRuntimeJsonPath(previousOtherJsonPath);
|
||||
Environment.SetEnvironmentVariable(OpenXRRuntimeSelector.RuntimeDetector.k_RuntimeEnvKey, previousActiveRuntime);
|
||||
Environment.SetEnvironmentVariable(OpenXRRuntimeSelector.k_SelectedRuntimeEnvKey, previousSelectedRuntime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14582cceaceaa6949852ce064e85a84a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using Unity.XR.CoreUtils.Editor;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class OpenXRValidationTests
|
||||
{
|
||||
internal class FakeFeature : OpenXRFeature
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that IsRuleEnabled will be true at the correct time for a BuildValidationRule.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void IsRuleEnabledTest()
|
||||
{
|
||||
// Create a validation rule that is enabled when FakeFeature is active
|
||||
OpenXRFeature.ValidationRule testRule = new OpenXRFeature.ValidationRule(ScriptableObject.CreateInstance<FakeFeature>())
|
||||
{
|
||||
message = "Fake feature message.",
|
||||
checkPredicate = () => true,
|
||||
fixIt = () => { },
|
||||
error = false,
|
||||
errorEnteringPlaymode = false
|
||||
};
|
||||
|
||||
// Create the build validation rule for Standalone (arbitrarily picked)
|
||||
BuildValidationRule buildValidationRule = OpenXRProjectValidationRulesSetup.ConvertRuleToBuildValidationRule(testRule, BuildTargetGroup.Standalone);
|
||||
|
||||
// Since the feature isn't in the active Standalone settings, the rule should not be enabled.
|
||||
Assert.IsFalse(buildValidationRule.IsRuleEnabled());
|
||||
|
||||
// Temporarily add an enabled FakeFeature to the Standalone settings, and then restore the settings when the test is done.
|
||||
// The build validation rule should be enabled when we add the feature to the Standalone settings.
|
||||
OpenXRSettings standaloneSettings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Standalone);
|
||||
OpenXRFeature firstStandaloneSetting = standaloneSettings.features[0];
|
||||
try
|
||||
{
|
||||
FakeFeature fakeFeature = ScriptableObject.CreateInstance<FakeFeature>();
|
||||
fakeFeature.enabled = true;
|
||||
standaloneSettings.features[0] = fakeFeature;
|
||||
Assert.IsTrue(buildValidationRule.IsRuleEnabled());
|
||||
}
|
||||
finally
|
||||
{
|
||||
standaloneSettings.features[0] = firstStandaloneSetting;
|
||||
}
|
||||
|
||||
// Create another build validation rule for something else other than Standalone.
|
||||
// The build validation rule should not be enabled when we add the feature to the Standalone group.
|
||||
buildValidationRule = OpenXRProjectValidationRulesSetup.ConvertRuleToBuildValidationRule(testRule, BuildTargetGroup.WSA);
|
||||
standaloneSettings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Standalone);
|
||||
firstStandaloneSetting = standaloneSettings.features[0];
|
||||
try
|
||||
{
|
||||
FakeFeature fakeFeature = ScriptableObject.CreateInstance<FakeFeature>();
|
||||
fakeFeature.enabled = true;
|
||||
standaloneSettings.features[0] = fakeFeature;
|
||||
Assert.IsFalse(buildValidationRule.IsRuleEnabled());
|
||||
}
|
||||
finally
|
||||
{
|
||||
standaloneSettings.features[0] = firstStandaloneSetting;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8329db5b1413bf24f849af3e63602cd9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "Unity.XR.OpenXR.Tests.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:27619889b8ba8c24980f49ee34dbb44a",
|
||||
"GUID:0acc523941302664db1f4e527237feb3",
|
||||
"GUID:4847341ff46394e83bb78fbd0652937e",
|
||||
"GUID:96aa6ba065960476598f8f643e7252b6",
|
||||
"GUID:e40ba710768534012815d3193fa296cb",
|
||||
"GUID:2023fa18bf9504e98b11fe2174802802",
|
||||
"GUID:6150739e4dc7bff4d833306fd9d5a4f0",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:4ddd23ea56a3a40f0aa0036d1624a53e"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.inputsystem",
|
||||
"expression": "1.6.3",
|
||||
"define": "INPUT_SYSTEM_BINDING_VALIDATOR"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 666653aa92bac494b9db60410f5b51f0
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,158 @@
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Mock;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
[assembly: UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)]
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class XRLoaderLifecycleTests : OpenXRLoaderSetup
|
||||
{
|
||||
[Test]
|
||||
public void FullLifecycleOrder()
|
||||
{
|
||||
bool subsystemCreate = false;
|
||||
bool subsystemStart = false;
|
||||
bool hookInstanceProc = false;
|
||||
MockRuntime.Instance.TestCallback = (methodName, param) =>
|
||||
{
|
||||
switch (methodName)
|
||||
{
|
||||
case nameof(OpenXRFeature.HookGetInstanceProcAddr):
|
||||
Assert.IsFalse(subsystemCreate);
|
||||
Assert.IsFalse(subsystemStart);
|
||||
hookInstanceProc = true;
|
||||
break;
|
||||
|
||||
case nameof(OpenXRFeature.OnSubsystemCreate):
|
||||
Assert.IsTrue(hookInstanceProc);
|
||||
Assert.IsFalse(subsystemStart);
|
||||
subsystemCreate = true;
|
||||
break;
|
||||
|
||||
case nameof(OpenXRFeature.OnSubsystemStart):
|
||||
Assert.IsTrue(hookInstanceProc);
|
||||
Assert.IsTrue(subsystemCreate);
|
||||
subsystemStart = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
base.InitializeAndStart();
|
||||
|
||||
ProcessOpenXRMessageLoop();
|
||||
|
||||
Assert.IsTrue(hookInstanceProc);
|
||||
Assert.IsTrue(subsystemCreate);
|
||||
Assert.IsTrue(subsystemStart);
|
||||
|
||||
bool subsystemStop = false;
|
||||
bool subsystemDestroy = false;
|
||||
MockRuntime.Instance.TestCallback = (methodName, param) =>
|
||||
{
|
||||
switch (methodName)
|
||||
{
|
||||
case nameof(OpenXRFeature.OnSubsystemStop):
|
||||
Assert.IsFalse(subsystemDestroy);
|
||||
subsystemStop = true;
|
||||
break;
|
||||
|
||||
case nameof(OpenXRFeature.OnSubsystemDestroy):
|
||||
Assert.IsTrue(subsystemStop);
|
||||
subsystemDestroy = true;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
base.StopAndShutdown();
|
||||
|
||||
Assert.IsTrue(subsystemStop);
|
||||
Assert.IsTrue(subsystemDestroy);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InstanceCreate() => TestInstanceCreate(true, false);
|
||||
|
||||
[Test]
|
||||
public void InstanceCreateFail() => TestInstanceCreate(false, false);
|
||||
|
||||
[Test]
|
||||
public void InstanceCreateRequired() => TestInstanceCreate(true, true);
|
||||
|
||||
[Test]
|
||||
public void InstanceCreateFailRequired() => TestInstanceCreate(false, true);
|
||||
|
||||
public void TestInstanceCreate(bool result, bool required)
|
||||
{
|
||||
Loader.DisableValidationChecksOnEnteringPlaymode = true;
|
||||
bool instanceCreated = false;
|
||||
bool hookInstanceProcAddr = false;
|
||||
bool other = false;
|
||||
MockRuntime.Instance.TestCallback = (methodName, param) =>
|
||||
{
|
||||
switch (methodName)
|
||||
{
|
||||
case nameof(OpenXRFeature.OnInstanceCreate):
|
||||
instanceCreated = true;
|
||||
return result;
|
||||
|
||||
case nameof(OpenXRFeature.HookGetInstanceProcAddr):
|
||||
hookInstanceProcAddr = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
other = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
MockRuntime.Instance.required = required;
|
||||
base.InitializeAndStart();
|
||||
|
||||
Assert.IsTrue(instanceCreated);
|
||||
Assert.IsTrue(hookInstanceProcAddr);
|
||||
|
||||
if (required && !result)
|
||||
Assert.IsNull(OpenXRLoaderBase.Instance);
|
||||
else
|
||||
Assert.IsNotNull(OpenXRLoaderBase.Instance);
|
||||
|
||||
// A feature that fails that is not required should be disabled
|
||||
if (!result && !required)
|
||||
Assert.IsFalse(MockRuntime.Instance.enabled);
|
||||
|
||||
base.StopAndShutdown();
|
||||
|
||||
if (result)
|
||||
Assert.IsTrue(other);
|
||||
else
|
||||
// A feature that fails initialize should have no further callbacks
|
||||
Assert.IsFalse(other);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeinitWithoutInit()
|
||||
{
|
||||
bool callback = false;
|
||||
MockRuntime.Instance.TestCallback = (methodName, param) =>
|
||||
{
|
||||
callback = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
base.StopAndShutdown();
|
||||
|
||||
Assert.IsFalse(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd9093c836e64270bb8a8c79d98e0055
|
||||
timeCreated: 1586981136
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEditor.SceneManagement;
|
||||
|
||||
[assembly: UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)]
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
internal class aAssetBundleTests
|
||||
{
|
||||
[Test]
|
||||
public void BuildAssetBundle()
|
||||
{
|
||||
#if UNITY_EDITOR_WIN
|
||||
var target = BuildTarget.StandaloneWindows64;
|
||||
#elif UNITY_EDITOR_OSX
|
||||
var target = BuildTarget.StandaloneOSX;
|
||||
#else
|
||||
var target = BuildTarget.NoTarget;
|
||||
#endif
|
||||
|
||||
// Test is only valid if we have a valid build target and that build target is available
|
||||
if (target == BuildTarget.NoTarget || !BuildPipeline.IsBuildTargetSupported(BuildPipeline.GetBuildTargetGroup(target), target))
|
||||
return;
|
||||
|
||||
// Create an asset and add it to an asset bundle
|
||||
var scene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);
|
||||
EditorSceneManager.SaveScene(scene, "Assets/abtest.unity");
|
||||
AssetDatabase.Refresh();
|
||||
var importer = AssetImporter.GetAtPath("Assets/abtest.unity");
|
||||
importer.assetBundleName = "mocktest";
|
||||
|
||||
if (!Directory.Exists("mocktest/ab"))
|
||||
Directory.CreateDirectory("mocktest/ab");
|
||||
|
||||
// Build the asset bundle
|
||||
BuildPipeline.BuildAssetBundles("mocktest/ab", BuildAssetBundleOptions.ForceRebuildAssetBundle, target);
|
||||
|
||||
// Cleanup
|
||||
AssetDatabase.DeleteAsset("Assets/abtest.unity");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3bfe33a5f8e944b0be093f643d913262
|
||||
timeCreated: 1625861611
|
||||
310
Packages/com.unity.xr.openxr/Tests/Editor/zBuildHookTests.cs
Normal file
310
Packages/com.unity.xr.openxr/Tests/Editor/zBuildHookTests.cs
Normal file
@@ -0,0 +1,310 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Mock;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.Management;
|
||||
using UnityEngine.XR.OpenXR.Tests;
|
||||
using Assert = UnityEngine.Assertions.Assert;
|
||||
|
||||
namespace UnityEditor.XR.OpenXR.Tests
|
||||
{
|
||||
// If you change this file, be sure to run the "no players" tests on yamato.
|
||||
// APV jobs don't include "players" such as standalone, so `BuildMockPlayer()`
|
||||
// will fail during APV. The "no players" job on yamato will catch this.
|
||||
internal class zBuildHookTests : OpenXRLoaderSetup
|
||||
{
|
||||
internal static BuildReport BuildMockPlayer()
|
||||
{
|
||||
BuildPlayerOptions opts = new BuildPlayerOptions();
|
||||
#if UNITY_EDITOR_WIN
|
||||
opts.target = BuildTarget.StandaloneWindows64;
|
||||
#elif UNITY_EDITOR_OSX
|
||||
opts.target = BuildTarget.StandaloneOSX;
|
||||
#endif
|
||||
if (File.Exists("Assets/main.unity"))
|
||||
opts.scenes = new string[] { "Assets/main.unity" };
|
||||
opts.targetGroup = BuildTargetGroup.Standalone;
|
||||
opts.locationPathName = "mocktest/mocktest.exe";
|
||||
|
||||
UnityEngine.TestTools.LogAssert.ignoreFailingMessages = true;
|
||||
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, opts.target);
|
||||
var report = BuildPipeline.BuildPlayer(opts);
|
||||
UnityEngine.TestTools.LogAssert.ignoreFailingMessages = false;
|
||||
return report;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PrePostCallbacksAreReceived()
|
||||
{
|
||||
bool preprocessCalled = false;
|
||||
bool postprocessCalled = false;
|
||||
|
||||
BuildCallbacks.TestCallback = (methodName, param) =>
|
||||
{
|
||||
if (methodName == "OnPreprocessBuildExt")
|
||||
{
|
||||
preprocessCalled = true;
|
||||
}
|
||||
|
||||
if (methodName == "OnPostprocessBuildExt")
|
||||
{
|
||||
postprocessCalled = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var result = BuildMockPlayer();
|
||||
|
||||
if (Environment.GetEnvironmentVariable("UNITY_OPENXR_YAMATO") == "1")
|
||||
Assert.IsTrue(result.summary.result == BuildResult.Succeeded);
|
||||
else if (result.summary.result != BuildResult.Succeeded)
|
||||
return;
|
||||
|
||||
Assert.IsTrue(preprocessCalled);
|
||||
Assert.IsTrue(postprocessCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NoBuildCallbacksFeatureDisabled()
|
||||
{
|
||||
bool preprocessCalled = false;
|
||||
bool postprocessCalled = false;
|
||||
|
||||
BuildCallbacks.TestCallback = (methodName, param) =>
|
||||
{
|
||||
if (methodName == "OnPreprocessBuildExt")
|
||||
{
|
||||
preprocessCalled = true;
|
||||
}
|
||||
|
||||
if (methodName == "OnPostprocessBuildExt")
|
||||
{
|
||||
postprocessCalled = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// Disable mock runtime, no callbacks should occur during build
|
||||
EnableFeature<MockRuntime>(false);
|
||||
BuildMockPlayer();
|
||||
Assert.IsFalse(preprocessCalled);
|
||||
Assert.IsFalse(postprocessCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NoBuildCallbacksOpenXRDisabled()
|
||||
{
|
||||
bool preprocessCalled = false;
|
||||
bool postprocessCalled = false;
|
||||
|
||||
BuildCallbacks.TestCallback = (methodName, param) =>
|
||||
{
|
||||
if (methodName == "OnPreprocessBuildExt")
|
||||
{
|
||||
preprocessCalled = true;
|
||||
}
|
||||
|
||||
if (methodName == "OnPostprocessBuildExt")
|
||||
{
|
||||
postprocessCalled = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// Remove OpenXR Loader, no callbacks should occur during build
|
||||
var loaders = XRGeneralSettings.Instance.Manager.activeLoaders;
|
||||
XRGeneralSettings.Instance.Manager.TrySetLoaders(new List<XRLoader>());
|
||||
BuildMockPlayer();
|
||||
XRGeneralSettings.Instance.Manager.TrySetLoaders(new List<XRLoader>(loaders));
|
||||
Assert.IsFalse(preprocessCalled);
|
||||
Assert.IsFalse(postprocessCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyBootConfigWrite()
|
||||
{
|
||||
bool preprocessCalled = false;
|
||||
bool postprocessCalled = false;
|
||||
|
||||
BootConfigTests.TestCallback = (methodName, param) =>
|
||||
{
|
||||
if (methodName == "OnPreprocessBuildExt")
|
||||
{
|
||||
preprocessCalled = true;
|
||||
}
|
||||
|
||||
if (methodName == "OnPostprocessBuildExt")
|
||||
{
|
||||
postprocessCalled = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var result = BuildMockPlayer();
|
||||
BuildMockPlayer();
|
||||
Assert.IsFalse(preprocessCalled);
|
||||
Assert.IsFalse(postprocessCalled);
|
||||
|
||||
BootConfigTests.EnsureCleanupFromLastRun();
|
||||
}
|
||||
|
||||
private bool HasOpenXRLibraries(BuildReport report)
|
||||
{
|
||||
var path = Path.GetDirectoryName(report.summary.outputPath);
|
||||
var dir = new DirectoryInfo(path);
|
||||
|
||||
var ext = "dll";
|
||||
if (Application.platform == RuntimePlatform.OSXEditor)
|
||||
ext = "dylib";
|
||||
|
||||
var dlls = dir.EnumerateFiles($"*.{ext}", SearchOption.AllDirectories).Select(s => s.Name).ToList();
|
||||
return dlls.Contains($"openxr_loader.{ext}") || dlls.Contains($"UnityOpenXR.{ext}");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyBuildOutputLibraries()
|
||||
{
|
||||
var resultWithOpenXR = BuildMockPlayer();
|
||||
|
||||
// Disable this test if we're not running our openxr yamato infrastructure
|
||||
if (resultWithOpenXR.summary.result != BuildResult.Succeeded && Environment.GetEnvironmentVariable("UNITY_OPENXR_YAMATO") != "1")
|
||||
return;
|
||||
|
||||
Assert.IsTrue(HasOpenXRLibraries(resultWithOpenXR));
|
||||
|
||||
// Remove OpenXR Loader
|
||||
XRGeneralSettings.Instance.Manager.TrySetLoaders(new List<XRLoader>());
|
||||
var resultWithoutOpenXR = BuildMockPlayer();
|
||||
Assert.IsFalse(HasOpenXRLibraries(resultWithoutOpenXR));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyBuildWithoutAnalytics()
|
||||
{
|
||||
var packageName = "com.unity.analytics";
|
||||
UnityEditor.PackageManager.Client.Remove(packageName);
|
||||
|
||||
var result = BuildMockPlayer();
|
||||
|
||||
if (Environment.GetEnvironmentVariable("UNITY_OPENXR_YAMATO") == "1")
|
||||
Assert.IsTrue(result.summary.result == BuildResult.Succeeded);
|
||||
else if (result.summary.result != BuildResult.Succeeded)
|
||||
return;
|
||||
}
|
||||
|
||||
internal class BuildCallbacks : OpenXRFeatureBuildHooks
|
||||
{
|
||||
[NonSerialized] internal static Func<string, object, bool> TestCallback = (methodName, param) => true;
|
||||
|
||||
public override int callbackOrder => 1;
|
||||
public override Type featureType => typeof(MockRuntime);
|
||||
|
||||
protected override void OnPreprocessBuildExt(BuildReport report)
|
||||
{
|
||||
TestCallback(MethodBase.GetCurrentMethod().Name, report);
|
||||
}
|
||||
|
||||
protected override void OnPostGenerateGradleAndroidProjectExt(string path)
|
||||
{
|
||||
TestCallback(MethodBase.GetCurrentMethod().Name, path);
|
||||
}
|
||||
|
||||
protected override void OnPostprocessBuildExt(BuildReport report)
|
||||
{
|
||||
TestCallback(MethodBase.GetCurrentMethod().Name, report);
|
||||
}
|
||||
|
||||
protected override void OnProcessBootConfigExt(BuildReport report, BootConfigBuilder builder)
|
||||
{
|
||||
TestCallback(MethodBase.GetCurrentMethod().Name, report);
|
||||
}
|
||||
}
|
||||
|
||||
internal class BootConfigTests : OpenXRFeatureBuildHooks
|
||||
{
|
||||
[NonSerialized] internal static Func<string, object, bool> TestCallback = (methodName, param) => true;
|
||||
|
||||
public override int callbackOrder => 1;
|
||||
public override Type featureType => typeof(MockRuntime);
|
||||
|
||||
// For this test, we want to ensure that the last run actually cleans up any settings that we've
|
||||
// stored into the boot settings of the EditorUserBuildSettings. We need the last run BuildReport
|
||||
// in order to check the EditorUserBuildSettings.
|
||||
private static BuildReport s_lastRunBuildReport;
|
||||
|
||||
protected override void OnPreprocessBuildExt(BuildReport report)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnPostGenerateGradleAndroidProjectExt(string path)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnPostprocessBuildExt(BuildReport report)
|
||||
{
|
||||
// check to see if we've got the boot config written into the UserSettings
|
||||
var bootConfig = new BootConfig(report);
|
||||
bootConfig.ReadBootConfig();
|
||||
Assert.IsTrue(bootConfig.TryGetValue("key-01", out var key01Value));
|
||||
Assert.AreEqual(key01Value, "primary test value");
|
||||
Assert.IsTrue(bootConfig.TryGetValue("key-02", out var key02Value));
|
||||
Assert.AreEqual(key02Value, "secondary test value");
|
||||
Assert.IsTrue(bootConfig.TryGetValue("key-03", out var key03Value));
|
||||
Assert.AreEqual(key03Value, "1");
|
||||
Assert.IsTrue(bootConfig.TryGetValue("key-04", out var key04Value));
|
||||
Assert.AreEqual(key04Value, "0");
|
||||
|
||||
s_lastRunBuildReport = report;
|
||||
}
|
||||
|
||||
protected override void OnProcessBootConfigExt(BuildReport report, BootConfigBuilder builder)
|
||||
{
|
||||
// Now we set some boot config values and check to make sure they're there.
|
||||
builder.SetBootConfigValue("key-01", "primary test value");
|
||||
builder.SetBootConfigValue("key-02", "secondary test value");
|
||||
builder.SetBootConfigBoolean("key-03", true);
|
||||
builder.SetBootConfigBoolean("key-04", false);
|
||||
Assert.IsTrue(builder.TryGetBootConfigValue("key-01", out var result01));
|
||||
Assert.AreEqual(result01, "primary test value");
|
||||
Assert.IsTrue(builder.TryGetBootConfigValue("key-02", out var result02));
|
||||
Assert.AreEqual(result02, "secondary test value");
|
||||
Assert.IsTrue(builder.TryGetBootConfigBoolean("key-03", out var result03));
|
||||
Assert.IsTrue(result03);
|
||||
Assert.IsTrue(builder.TryGetBootConfigBoolean("key-04", out var result04));
|
||||
Assert.IsFalse(result04);
|
||||
builder.SetBootConfigValue("key-05", "remove-me");
|
||||
Assert.IsTrue(builder.TryRemoveBootConfigEntry("key-05"));
|
||||
Assert.IsFalse(builder.TryGetBootConfigValue("key-05", out var result05));
|
||||
Assert.IsFalse(builder.TryGetBootConfigBoolean("key-999", out var result06));
|
||||
Assert.IsFalse(result06);
|
||||
}
|
||||
|
||||
public static void EnsureCleanupFromLastRun()
|
||||
{
|
||||
// make sure that the UserSettings doesn't hold any additional configs we've previously written
|
||||
if (s_lastRunBuildReport == null)
|
||||
return;
|
||||
|
||||
var bootConfig = new BootConfig(s_lastRunBuildReport);
|
||||
bootConfig.ReadBootConfig();
|
||||
Assert.IsFalse(bootConfig.TryGetValue("key-01", out var key01Value));
|
||||
Assert.IsFalse(bootConfig.TryGetValue("key-02", out var key02Value));
|
||||
Assert.IsFalse(bootConfig.TryGetValue("key-03", out var key03Value));
|
||||
Assert.IsFalse(bootConfig.TryGetValue("key-04", out var key04Value));
|
||||
Assert.IsFalse(bootConfig.TryGetValue("key-05", out var key05Value));
|
||||
|
||||
s_lastRunBuildReport = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a0dc36717c904db4ab68f42baa559da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,372 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
|
||||
class zBuildSamplesYamatoOnly
|
||||
{
|
||||
struct SampleBuildTargetSetup
|
||||
{
|
||||
public BuildTarget buildTarget;
|
||||
public BuildTargetGroup targetGroup;
|
||||
public Action<string, string> setupPlayerSettings;
|
||||
public string outputPostfix;
|
||||
public Regex sampleRegex;
|
||||
}
|
||||
|
||||
static void WriteAndroidInstallerScripts(string outputFile, string identifier)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(outputFile);
|
||||
if (dir == null) return;
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
var scripts = new string[] { "install.command", "install.bat" };
|
||||
foreach (var script in scripts)
|
||||
{
|
||||
var scriptPath = Path.Combine(dir, script);
|
||||
|
||||
var scriptContents = $"adb uninstall {identifier}\n" +
|
||||
$"adb install \"{Path.GetFileName(outputFile)}\"\n\n";
|
||||
|
||||
File.AppendAllText(scriptPath, scriptContents);
|
||||
}
|
||||
}
|
||||
|
||||
static void EnableQuestFeature()
|
||||
{
|
||||
foreach (var feature in OpenXRSettings.ActiveBuildTargetInstance.features)
|
||||
{
|
||||
if (String.Compare(feature.featureIdInternal, "com.unity.openxr.feature.metaquest", true) == 0)
|
||||
{
|
||||
Console.WriteLine($"Enable: {feature.nameUi}");
|
||||
feature.enabled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Assert.IsTrue(false, "Could not enable meta quest extension - if you're not on build machine you must copy dir MetaQuest to your project.");
|
||||
}
|
||||
|
||||
static void EnableMSFTObserverFeature()
|
||||
{
|
||||
foreach (var feature in OpenXRSettings.ActiveBuildTargetInstance.features)
|
||||
{
|
||||
if (String.Compare(feature.featureIdInternal, "com.unity.openxr.feature.example.msftobserver", true) == 0)
|
||||
{
|
||||
Console.WriteLine($"Enable: {feature.nameUi}");
|
||||
feature.enabled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void EnableFeature<TFeatureType>() where TFeatureType : OpenXRFeature
|
||||
{
|
||||
foreach (var feature in OpenXRSettings.ActiveBuildTargetInstance.features)
|
||||
{
|
||||
if (feature is TFeatureType)
|
||||
{
|
||||
Console.WriteLine($"Enable: {feature.nameUi}");
|
||||
feature.enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void EnableSampleFeatures()
|
||||
{
|
||||
foreach (var feature in OpenXRSettings.ActiveBuildTargetInstance.features)
|
||||
{
|
||||
if (feature.GetType().Namespace == null)
|
||||
{
|
||||
throw new Exception("All code in the OpenXR Package must be in a namespace.");
|
||||
}
|
||||
|
||||
if (feature.GetType().Namespace.StartsWith("UnityEngine.XR.OpenXR.Samples"))
|
||||
{
|
||||
Console.WriteLine($"Enable: {feature.nameUi}");
|
||||
feature.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void EnableStandaloneProfiles()
|
||||
{
|
||||
EnableFeature<MicrosoftHandInteraction>();
|
||||
EnableFeature<MicrosoftMotionControllerProfile>();
|
||||
EnableFeature<HTCViveControllerProfile>();
|
||||
EnableFeature<ValveIndexControllerProfile>();
|
||||
EnableFeature<OculusTouchControllerProfile>();
|
||||
EnableFeature<MetaQuestTouchProControllerProfile>();
|
||||
EnableFeature<HandInteractionProfile>();
|
||||
EnableFeature<PalmPoseInteraction>();
|
||||
EnableFeature<DPadInteraction>();
|
||||
EnableFeature<HandCommonPosesInteraction>();
|
||||
}
|
||||
|
||||
static void EnableWSAProfiles()
|
||||
{
|
||||
EnableFeature<MicrosoftHandInteraction>();
|
||||
EnableFeature<EyeGazeInteraction>();
|
||||
EnableFeature<MicrosoftMotionControllerProfile>();
|
||||
EnableFeature<HandInteractionProfile>();
|
||||
EnableFeature<PalmPoseInteraction>();
|
||||
EnableFeature<HandCommonPosesInteraction>();
|
||||
}
|
||||
|
||||
static void EnableAndroidProfiles()
|
||||
{
|
||||
EnableFeature<OculusTouchControllerProfile>();
|
||||
EnableFeature<MetaQuestTouchProControllerProfile>();
|
||||
}
|
||||
|
||||
static SampleBuildTargetSetup[] buildTargetSetup =
|
||||
{
|
||||
#if UNITY_EDITOR_WIN
|
||||
new SampleBuildTargetSetup
|
||||
{
|
||||
buildTarget = BuildTarget.StandaloneWindows64,
|
||||
targetGroup = BuildTargetGroup.Standalone,
|
||||
setupPlayerSettings = (outputFile, identifier) =>
|
||||
{
|
||||
EnableSampleFeatures();
|
||||
EnableStandaloneProfiles();
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.StandaloneWindows64, new[] { GraphicsDeviceType.Direct3D11, GraphicsDeviceType.Vulkan });
|
||||
OpenXRSettings.ActiveBuildTargetInstance.depthSubmissionMode = OpenXRSettings.DepthSubmissionMode.Depth24Bit;
|
||||
},
|
||||
outputPostfix = "dx11",
|
||||
},
|
||||
new SampleBuildTargetSetup
|
||||
{
|
||||
sampleRegex = new Regex(".*Render.*"), // Only build dx12 variant for Render Samples
|
||||
buildTarget = BuildTarget.StandaloneWindows64,
|
||||
targetGroup = BuildTargetGroup.Standalone,
|
||||
setupPlayerSettings = (outputFile, identifier) =>
|
||||
{
|
||||
EnableSampleFeatures();
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.StandaloneWindows64, new[] { GraphicsDeviceType.Direct3D12, GraphicsDeviceType.Direct3D11 });
|
||||
QualitySettings.SetQualityLevel(5);
|
||||
QualitySettings.antiAliasing = 4;
|
||||
},
|
||||
outputPostfix = "dx12",
|
||||
},
|
||||
new SampleBuildTargetSetup
|
||||
{
|
||||
sampleRegex = new Regex(".*Render.*"), // Only build vulkan variant for Render Samples
|
||||
buildTarget = BuildTarget.StandaloneWindows64,
|
||||
targetGroup = BuildTargetGroup.Standalone,
|
||||
setupPlayerSettings = (outputFile, identifier) =>
|
||||
{
|
||||
EnableSampleFeatures();
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.StandaloneWindows64, new[] { GraphicsDeviceType.Vulkan, GraphicsDeviceType.Direct3D11 });
|
||||
OpenXRSettings.ActiveBuildTargetInstance.depthSubmissionMode = OpenXRSettings.DepthSubmissionMode.Depth24Bit;
|
||||
},
|
||||
outputPostfix = "vk",
|
||||
},
|
||||
new SampleBuildTargetSetup
|
||||
{
|
||||
buildTarget = BuildTarget.WSAPlayer,
|
||||
targetGroup = BuildTargetGroup.WSA,
|
||||
setupPlayerSettings = (outputFile, identifier) =>
|
||||
{
|
||||
EnableSampleFeatures();
|
||||
EnableMSFTObserverFeature();
|
||||
EnableFeature<EyeGazeInteraction>();
|
||||
EnableFeature<MicrosoftHandInteraction>();
|
||||
EnableWSAProfiles();
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.WSAPlayer, new[] { GraphicsDeviceType.Direct3D11 });
|
||||
PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.GazeInput, true);
|
||||
#if UNITY_2021_3_OR_NEWER
|
||||
PlayerSettings.WSA.packageName = PlayerSettings.GetApplicationIdentifier(NamedBuildTarget.WindowsStoreApps);
|
||||
#else
|
||||
PlayerSettings.WSA.packageName = PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.WSA);
|
||||
#endif
|
||||
OpenXRSettings.ActiveBuildTargetInstance.renderMode = OpenXRSettings.RenderMode.SinglePassInstanced;
|
||||
OpenXRSettings.ActiveBuildTargetInstance.depthSubmissionMode = OpenXRSettings.DepthSubmissionMode.Depth16Bit;
|
||||
},
|
||||
outputPostfix = "dx11",
|
||||
},
|
||||
new SampleBuildTargetSetup
|
||||
{
|
||||
sampleRegex = new Regex(".*Render.*"), // Only build dx12 variant for Render Samples
|
||||
buildTarget = BuildTarget.WSAPlayer,
|
||||
targetGroup = BuildTargetGroup.WSA,
|
||||
setupPlayerSettings = (outputFile, identifier) =>
|
||||
{
|
||||
EnableSampleFeatures();
|
||||
EnableMSFTObserverFeature();
|
||||
EnableFeature<EyeGazeInteraction>();
|
||||
EnableFeature<MicrosoftHandInteraction>();
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.WSAPlayer, new[] { GraphicsDeviceType.Direct3D12 });
|
||||
QualitySettings.SetQualityLevel(5);
|
||||
QualitySettings.antiAliasing = 4;
|
||||
#if UNITY_2021_3_OR_NEWER
|
||||
PlayerSettings.WSA.packageName = PlayerSettings.GetApplicationIdentifier(NamedBuildTarget.WindowsStoreApps);
|
||||
#else
|
||||
PlayerSettings.WSA.packageName = PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.WSA);
|
||||
#endif
|
||||
PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.GazeInput, true);
|
||||
},
|
||||
outputPostfix = "dx12",
|
||||
},
|
||||
#endif
|
||||
new SampleBuildTargetSetup
|
||||
{
|
||||
sampleRegex = new Regex(".*Render.*|.*MetaSample.*"), // Only build vulkan variant for Render Samples
|
||||
buildTarget = BuildTarget.Android,
|
||||
targetGroup = BuildTargetGroup.Android,
|
||||
setupPlayerSettings = (outputFile, identifier) =>
|
||||
{
|
||||
EnableSampleFeatures();
|
||||
EnableQuestFeature();
|
||||
EnableAndroidProfiles();
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.Android, new[] { GraphicsDeviceType.Vulkan, GraphicsDeviceType.OpenGLES3 });
|
||||
PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel25;
|
||||
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
|
||||
#if UNITY_2021_3_OR_NEWER
|
||||
PlayerSettings.SetScriptingBackend(NamedBuildTarget.Android, ScriptingImplementation.IL2CPP);
|
||||
#else
|
||||
PlayerSettings.SetScriptingBackend(BuildTargetGroup.Android, ScriptingImplementation.IL2CPP);
|
||||
#endif
|
||||
WriteAndroidInstallerScripts(outputFile, identifier);
|
||||
OpenXRSettings.ActiveBuildTargetInstance.depthSubmissionMode = OpenXRSettings.DepthSubmissionMode.Depth16Bit;
|
||||
},
|
||||
outputPostfix = "arm64_vk",
|
||||
},
|
||||
new SampleBuildTargetSetup
|
||||
{
|
||||
sampleRegex = new Regex("^(?!.*MetaSample).*$"), // Don't build the Meta Sample for GLES
|
||||
buildTarget = BuildTarget.Android,
|
||||
targetGroup = BuildTargetGroup.Android,
|
||||
setupPlayerSettings = (outputFile, identifier) =>
|
||||
{
|
||||
EnableSampleFeatures();
|
||||
EnableQuestFeature();
|
||||
EnableAndroidProfiles();
|
||||
PlayerSettings.SetUseDefaultGraphicsAPIs(BuildTarget.Android, false);
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.Android, new[] { GraphicsDeviceType.OpenGLES3, GraphicsDeviceType.Vulkan });
|
||||
PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel25;
|
||||
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
|
||||
#if UNITY_2021_3_OR_NEWER
|
||||
PlayerSettings.SetScriptingBackend(NamedBuildTarget.Android, ScriptingImplementation.IL2CPP);
|
||||
#else
|
||||
PlayerSettings.SetScriptingBackend(BuildTargetGroup.Android, ScriptingImplementation.IL2CPP);
|
||||
#endif
|
||||
WriteAndroidInstallerScripts(outputFile, identifier);
|
||||
OpenXRSettings.ActiveBuildTargetInstance.depthSubmissionMode = OpenXRSettings.DepthSubmissionMode.Depth16Bit;
|
||||
},
|
||||
outputPostfix = "arm64_gles3",
|
||||
},
|
||||
};
|
||||
|
||||
static string GetBuildFileExt(BuildTarget target)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case BuildTarget.Android:
|
||||
return ".apk";
|
||||
case BuildTarget.StandaloneWindows:
|
||||
case BuildTarget.StandaloneWindows64:
|
||||
return ".exe";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static string GetResultDir()
|
||||
{
|
||||
bool next = false;
|
||||
foreach (var arg in System.Environment.GetCommandLineArgs())
|
||||
{
|
||||
if (next)
|
||||
return arg;
|
||||
|
||||
if (arg == "-resultDir")
|
||||
next = true;
|
||||
}
|
||||
return "OpenXR Samples";
|
||||
}
|
||||
|
||||
static void BuildSamples()
|
||||
{
|
||||
string resultDir = GetResultDir();
|
||||
|
||||
Console.WriteLine("Result Dir: " + resultDir);
|
||||
|
||||
var sampleName = "Unknown Sample";
|
||||
var projSamplesDir = new DirectoryInfo("Assets/Sample");
|
||||
if (projSamplesDir.Exists)
|
||||
{
|
||||
// Use the directory name in the samples directory, if it exists
|
||||
sampleName = projSamplesDir.GetDirectories()[0].Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise use the current folder as the project name
|
||||
projSamplesDir = new DirectoryInfo("Assets");
|
||||
sampleName = new DirectoryInfo(".").Name;
|
||||
}
|
||||
|
||||
PlayerSettings.colorSpace = ColorSpace.Linear;
|
||||
FeatureHelpers.RefreshFeatures(EditorUserBuildSettings.selectedBuildTargetGroup);
|
||||
|
||||
foreach (var setup in buildTargetSetup)
|
||||
{
|
||||
if (setup.sampleRegex != null && !setup.sampleRegex.Match(sampleName).Success)
|
||||
continue;
|
||||
|
||||
if (EditorUserBuildSettings.activeBuildTarget != setup.buildTarget)
|
||||
continue;
|
||||
|
||||
string outputDir = Path.Combine(resultDir, setup.buildTarget.ToString());
|
||||
|
||||
string identifier = "com.openxr." + sampleName + "." + setup.outputPostfix;
|
||||
#if UNITY_2021_3_OR_NEWER
|
||||
PlayerSettings.SetApplicationIdentifier(NamedBuildTarget.FromBuildTargetGroup(setup.targetGroup), identifier);
|
||||
#else
|
||||
PlayerSettings.SetApplicationIdentifier(setup.targetGroup, identifier);
|
||||
#endif
|
||||
PlayerSettings.productName = "OpenXR " + sampleName + " " + setup.outputPostfix;
|
||||
Console.WriteLine("=========== Setting up player settings (changing graphics apis)");
|
||||
string outputFile = Path.Combine(outputDir,
|
||||
PlayerSettings.productName + GetBuildFileExt(setup.buildTarget));
|
||||
setup.setupPlayerSettings(outputFile, identifier);
|
||||
|
||||
// Get the list of scenes set in build settings in the project
|
||||
var scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray();
|
||||
|
||||
// If there aren't any, just build all of the scenes found in the sample
|
||||
if (scenes.Length == 0)
|
||||
{
|
||||
scenes = Directory.GetFiles(projSamplesDir.FullName, "*.unity", SearchOption.AllDirectories);
|
||||
}
|
||||
|
||||
BuildPlayerOptions buildOptions = new BuildPlayerOptions
|
||||
{
|
||||
scenes = scenes,
|
||||
target = setup.buildTarget,
|
||||
targetGroup = setup.targetGroup,
|
||||
locationPathName = outputFile,
|
||||
};
|
||||
Console.WriteLine($"=========== Building {sampleName} {setup.buildTarget}_{setup.outputPostfix}");
|
||||
var report = BuildPipeline.BuildPlayer(buildOptions);
|
||||
Console.WriteLine($"=========== Build Result {sampleName} {setup.buildTarget}_{setup.outputPostfix} {report.summary.result}");
|
||||
|
||||
if (report.summary.result == BuildResult.Failed)
|
||||
{
|
||||
EditorApplication.Exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b539520d5a342436b8ee4abb353fd33b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user