diff --git a/Assets/MediaPipeUnity/Samples/Common/Scripts/AssetLoader.cs b/Assets/MediaPipeUnity/Samples/Common/Scripts/AssetLoader.cs index a312f355a..d649156be 100644 --- a/Assets/MediaPipeUnity/Samples/Common/Scripts/AssetLoader.cs +++ b/Assets/MediaPipeUnity/Samples/Common/Scripts/AssetLoader.cs @@ -10,9 +10,9 @@ namespace Mediapipe.Unity.Sample { public static class AssetLoader { - private static ResourceManager _ResourceManager; + private static IResourceManager _ResourceManager; - public static void Provide(ResourceManager manager) => _ResourceManager = manager; + public static void Provide(IResourceManager manager) => _ResourceManager = manager; public static IEnumerator PrepareAssetAsync(string name, string uniqueKey, bool overwrite = false) { diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Util/ResourceUtil_Safe.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Util/ResourceUtil_Safe.cs index 47adbfd49..e3812f08c 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Util/ResourceUtil_Safe.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Util/ResourceUtil_Safe.cs @@ -12,10 +12,10 @@ internal static partial class SafeNativeMethods { [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern void mp__SetCustomGlobalResourceProvider__P( - [MarshalAs(UnmanagedType.FunctionPtr)] ResourceManager.NativeResourceProvider provider); + [MarshalAs(UnmanagedType.FunctionPtr)] ResourceUtil.NativeResourceProvider provider); [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern void mp__SetCustomGlobalPathResolver__P( - [MarshalAs(UnmanagedType.FunctionPtr)] ResourceManager.PathResolver resolver); + [MarshalAs(UnmanagedType.FunctionPtr)] ResourceUtil.PathResolver resolver); } } diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager.cs new file mode 100644 index 000000000..98cf8df38 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. +using System.Collections; + +namespace Mediapipe.Unity +{ + public interface IResourceManager + { + /// + /// Saves as asynchronously. + /// + /// + /// To make it possible for MediaPipe to read the saved asset, the asset path must be registered + /// by calling or internally. + /// + /// + /// Specifies whether will be overwritten if it already exists. + /// + public IEnumerator PrepareAssetAsync(string name, string uniqueKey, bool overwrite = true); + + public IEnumerator PrepareAssetAsync(string name, bool overwrite = true) => PrepareAssetAsync(name, name, overwrite); + } +} diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceManager.cs.meta b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager.cs.meta similarity index 83% rename from Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceManager.cs.meta rename to Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager.cs.meta index ca1c57bdb..ed0006b08 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceManager.cs.meta +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a4e51cc091c70c661943c15038a905da +guid: 55e73e173dbbdbfb2bbe22a790b86a13 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/AssetBundleResourceManager.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/AssetBundleResourceManager.cs index a6dd391b9..19ebec75a 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/AssetBundleResourceManager.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/AssetBundleResourceManager.cs @@ -4,35 +4,26 @@ // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. -using System; using System.Collections; using System.IO; using UnityEngine; namespace Mediapipe.Unity { - public class AssetBundleResourceManager : ResourceManager + public class AssetBundleResourceManager : IResourceManager { private static readonly string _TAG = nameof(AssetBundleResourceManager); private static string _AssetBundlePath; private static string _CachePathRoot; - public AssetBundleResourceManager(string assetBundleName, string cachePath = "Cache") : base(PathToResourceAsFile, GetResourceContents) + public AssetBundleResourceManager(string assetBundleName, string cachePath = "Cache") { - // It's safe to update static members because at most one RsourceManager can be initialized. + ResourceUtil.EnableCustomResolver(); _AssetBundlePath = Path.Combine(Application.streamingAssetsPath, assetBundleName); _CachePathRoot = Path.Combine(Application.persistentDataPath, cachePath); } - public override bool IsPrepared(string name) - { - var path = GetCachePathFor(name); - - return File.Exists(path); - } - - private AssetBundleCreateRequest _assetBundleReq; private AssetBundle assetBundle => _assetBundleReq?.assetBundle; @@ -62,9 +53,17 @@ public IEnumerator LoadAssetBundleAsync() } } - public override IEnumerator PrepareAssetAsync(string name, string uniqueKey, bool overwrite = true) + IEnumerator IResourceManager.PrepareAssetAsync(string name, string uniqueKey, bool overwrite) { var destFilePath = GetCachePathFor(uniqueKey); + if (overwrite) + { + ResourceUtil.SetAssetPath(name, destFilePath); + } + else + { + ResourceUtil.AddAssetPath(name, destFilePath); + } if (File.Exists(destFilePath) && !overwrite) { @@ -95,20 +94,6 @@ public override IEnumerator PrepareAssetAsync(string name, string uniqueKey, boo Logger.LogVerbose(_TAG, $"{name} is saved to {destFilePath} (length={bytes.Length})"); } - protected static string PathToResourceAsFile(string assetPath) - { - var assetName = GetAssetNameFromPath(assetPath); - return GetCachePathFor(assetName); - } - - protected static byte[] GetResourceContents(string path) - { - Logger.LogDebug($"{path} is requested"); - - var cachePath = PathToResourceAsFile(path); - return File.ReadAllBytes(cachePath); - } - private static string GetCachePathFor(string assetName) { return Path.Combine(_CachePathRoot, assetName); diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/LocalResourceManager.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/LocalResourceManager.cs index 5838f672d..e5e4b28a0 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/LocalResourceManager.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/LocalResourceManager.cs @@ -12,7 +12,7 @@ namespace Mediapipe.Unity { - public class LocalResourceManager : ResourceManager + public class LocalResourceManager : IResourceManager { private static readonly string _TAG = nameof(LocalResourceManager); @@ -20,23 +20,26 @@ public class LocalResourceManager : ResourceManager private static readonly string _AssetPathRoot = "Packages/com.github.homuler.mediapipe/PackageResources/MediaPipe"; private static string _CachePathRoot; - public LocalResourceManager(string path) : base(PathToResourceAsFile, GetResourceContents) + public LocalResourceManager(string path) { - // It's safe to update static members because at most one RsourceManager can be initialized. + ResourceUtil.EnableCustomResolver(); _RelativePath = path; _CachePathRoot = Path.Combine(Application.persistentDataPath, _RelativePath); } public LocalResourceManager() : this("") { } - public override bool IsPrepared(string assetName) - { - return File.Exists(GetCachePathFor(assetName)); - } - - public override IEnumerator PrepareAssetAsync(string name, string uniqueKey, bool overwrite = true) + IEnumerator IResourceManager.PrepareAssetAsync(string name, string uniqueKey, bool overwrite) { var destFilePath = GetCachePathFor(uniqueKey); + if (overwrite) + { + ResourceUtil.SetAssetPath(name, destFilePath); + } + else + { + ResourceUtil.AddAssetPath(name, destFilePath); + } if (File.Exists(destFilePath) && !overwrite) { @@ -61,21 +64,6 @@ public override IEnumerator PrepareAssetAsync(string name, string uniqueKey, boo Logger.LogVerbose(_TAG, $"{name} is saved to {destFilePath} (length={asset.bytes.Length})"); } - protected static string PathToResourceAsFile(string assetPath) - { - var assetName = GetAssetNameFromPath(assetPath); - return GetCachePathFor(assetName); - } - - protected static byte[] GetResourceContents(string path) - { - // TODO: try AsyncReadManager - Logger.LogDebug($"{path} is requested"); - - var cachePath = PathToResourceAsFile(path); - return File.ReadAllBytes(cachePath); - } - private static string GetAssetPathFor(string assetName) { return Path.Combine(_AssetPathRoot, assetName); diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/StreamingAssetsResourceManager.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/StreamingAssetsResourceManager.cs index 62126ce74..ac16630ba 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/StreamingAssetsResourceManager.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/ResourceManager/StreamingAssetsResourceManager.cs @@ -11,7 +11,7 @@ namespace Mediapipe.Unity { - public class StreamingAssetsResourceManager : ResourceManager + public class StreamingAssetsResourceManager : IResourceManager { private static readonly string _TAG = nameof(StreamingAssetsResourceManager); @@ -19,9 +19,9 @@ public class StreamingAssetsResourceManager : ResourceManager private static string _AssetPathRoot; private static string _CachePathRoot; - public StreamingAssetsResourceManager(string path) : base(PathToResourceAsFile, GetResourceContents) + public StreamingAssetsResourceManager(string path) { - // It's safe to update static members because at most one RsourceManager can be initialized. + ResourceUtil.EnableCustomResolver(); _RelativePath = path; _AssetPathRoot = Path.Combine(Application.streamingAssetsPath, _RelativePath); _CachePathRoot = Path.Combine(Application.persistentDataPath, _RelativePath); @@ -29,16 +29,17 @@ public StreamingAssetsResourceManager(string path) : base(PathToResourceAsFile, public StreamingAssetsResourceManager() : this("") { } - public override bool IsPrepared(string name) - { - var path = GetCachePathFor(name); - - return File.Exists(path); - } - - public override IEnumerator PrepareAssetAsync(string name, string uniqueKey, bool overwrite = true) + IEnumerator IResourceManager.PrepareAssetAsync(string name, string uniqueKey, bool overwrite) { var destFilePath = GetCachePathFor(uniqueKey); + if (overwrite) + { + ResourceUtil.SetAssetPath(name, destFilePath); + } + else + { + ResourceUtil.AddAssetPath(name, destFilePath); + } if (File.Exists(destFilePath) && !overwrite) { @@ -62,21 +63,6 @@ public override IEnumerator PrepareAssetAsync(string name, string uniqueKey, boo Logger.LogVerbose(_TAG, $"{sourceFilePath} is copied to {destFilePath}"); } - protected static string PathToResourceAsFile(string assetPath) - { - var assetName = GetAssetNameFromPath(assetPath); - return GetCachePathFor(assetName); - } - - protected static byte[] GetResourceContents(string path) - { - // TODO: try AsyncReadManager - Logger.LogDebug($"{path} is requested"); - - var cachePath = PathToResourceAsFile(path); - return File.ReadAllBytes(cachePath); - } - private IEnumerator CreateCacheFile(string assetName) { var cacheFilePath = GetCachePathFor(assetName); diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceManager.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceManager.cs deleted file mode 100644 index 0ac3dedc5..000000000 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceManager.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2021 homuler -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file or at -// https://opensource.org/licenses/MIT. - -using System; -using System.Collections; -using System.IO; - -namespace Mediapipe -{ - /// - /// Class to manage assets that MediaPipe accesses. - /// - /// - /// There must not be more than one instance at the same time. - /// - public abstract class ResourceManager - { - public delegate string PathResolver(string path); - internal delegate bool NativeResourceProvider(string path, IntPtr dest); - public delegate byte[] ResourceProvider(string path); - - private static readonly object _InitLock = new object(); - private static ResourceManager _Instance; - private readonly PathResolver _pathResolver; - private readonly ResourceProvider _resourceProvider; - - public ResourceManager(PathResolver pathResolver, ResourceProvider resourceProvider) - { - lock (_InitLock) - { - if (_Instance != null) - { - throw new InvalidOperationException("ResourceManager can be initialized only once"); - } - _pathResolver = pathResolver; - _resourceProvider = resourceProvider; - SafeNativeMethods.mp__SetCustomGlobalPathResolver__P(PathToResourceAsFile); - SafeNativeMethods.mp__SetCustomGlobalResourceProvider__P(GetResourceContents); - _Instance = this; - } - } - - /// Asset name - /// - /// Returns true if is already prepared (saved locally on the device). - /// - public abstract bool IsPrepared(string name); - - /// - /// Saves as asynchronously. - /// - /// - /// Specifies whether will be overwritten if it already exists. - /// - public abstract IEnumerator PrepareAssetAsync(string name, string uniqueKey, bool overwrite = true); - - public IEnumerator PrepareAssetAsync(string name, bool overwrite = true) - { - return PrepareAssetAsync(name, name, overwrite); - } - - [AOT.MonoPInvokeCallback(typeof(PathResolver))] - private static string PathToResourceAsFile(string assetPath) - { - try - { - return _Instance._pathResolver(assetPath); - } - catch (Exception e) - { - UnityEngine.Debug.LogException(e); - return ""; - } - } - - [AOT.MonoPInvokeCallback(typeof(ResourceProvider))] - private static bool GetResourceContents(string path, IntPtr dst) - { - try - { - var asset = _Instance._resourceProvider(path); - using (var srcStr = new StdString(asset)) - { - srcStr.Swap(new StdString(dst, false)); - } - return true; - } - catch (Exception e) - { - UnityEngine.Debug.LogException(e); - return false; - } - } - - protected static string GetAssetNameFromPath(string assetPath) - { - var assetName = Path.GetFileNameWithoutExtension(assetPath); - var extension = Path.GetExtension(assetPath); - - switch (extension) - { - case ".binarypb": - case ".tflite": - { - return $"{assetName}.bytes"; - } - case ".pbtxt": - { - return $"{assetName}.txt"; - } - default: - { - return $"{assetName}{extension}"; - } - } - } - } -} diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceUtil.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceUtil.cs new file mode 100644 index 000000000..7f3464170 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceUtil.cs @@ -0,0 +1,155 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace Mediapipe +{ + public static class ResourceUtil + { + internal delegate string PathResolver(string path); + internal delegate bool NativeResourceProvider(string path, IntPtr dest); + + private static readonly string _TAG = nameof(ResourceUtil); + + private static bool _IsInitialized; + private static readonly Dictionary _AssetPathMap = new Dictionary(); + + public static void EnableCustomResolver() + { + if (_IsInitialized) + { + return; + } + SafeNativeMethods.mp__SetCustomGlobalPathResolver__P(PathToResourceAsFile); + SafeNativeMethods.mp__SetCustomGlobalResourceProvider__P(GetResourceContents); + _IsInitialized = true; + } + + /// + /// Registers the asset path to the resource manager. + /// + /// + /// The key to register the asset path. + /// It is usually the file path of the asset hard-coded in the native code (e.g. `path/to/model.tflite`) + /// or the asset name (e.g. `model.bytes`). + /// + /// + /// The file path of the asset. + /// + public static void SetAssetPath(string assetKey, string assetPath) => _AssetPathMap[assetKey] = assetPath; + + /// + /// Registers the asset path to the resource manager. + /// + /// + /// Thrown when the asset key is already registered + /// + /// + /// The key to register the asset path. + /// It is usually the file path of the asset hard-coded in the native code (e.g. `path/to/model.tflite`) + /// or the asset name (e.g. `model.bytes`). + /// + /// + /// The file path of the asset. + /// + public static void AddAssetPath(string assetKey, string assetPath) => _AssetPathMap.Add(assetKey, assetPath); + + /// + /// Removes the asset key from the resource manager. + /// + /// + public static bool RemoveAssetPath(string assetKey) => _AssetPathMap.Remove(assetKey); + + public static bool TryGetFilePath(string assetPath, out string filePath) + { + // try to find the file path by the requested asset path + if (_AssetPathMap.TryGetValue(assetPath, out filePath)) + { + return true; + } + // try to find the file path by the asset name + if (_AssetPathMap.TryGetValue(GetAssetNameFromPath(assetPath), out filePath)) + { + return true; + } + return false; + } + + [AOT.MonoPInvokeCallback(typeof(PathResolver))] + private static string PathToResourceAsFile(string assetPath) + { + UnityEngine.Debug.Log($"{assetPath} is requested"); + try + { + Logger.LogDebug(_TAG, $"{assetPath} is requested"); + if (TryGetFilePath(assetPath, out var filePath)) + { + return filePath; + } + throw new KeyNotFoundException($"Failed to find the file path for `{assetPath}`"); + } + catch (Exception e) + { + Logger.LogException(e); + return ""; + } + } + + [AOT.MonoPInvokeCallback(typeof(NativeResourceProvider))] + private static bool GetResourceContents(string path, IntPtr dst) + { + UnityEngine.Debug.Log($"{path} is requested"); + + try + { + Logger.LogDebug(_TAG, $"{path} is requested"); + + if (!TryGetFilePath(path, out var filePath)) + { + throw new KeyNotFoundException($"Failed to find the file path for `{path}`"); + } + + var asset = File.ReadAllBytes(filePath); + using (var srcStr = new StdString(asset)) + { + srcStr.Swap(new StdString(dst, false)); + } + return true; + } + catch (Exception e) + { + Logger.LogException(e); + return false; + } + } + + private static string GetAssetNameFromPath(string assetPath) + { + var assetName = Path.GetFileNameWithoutExtension(assetPath); + var extension = Path.GetExtension(assetPath); + + switch (extension) + { + case ".binarypb": + case ".tflite": + { + return $"{assetName}.bytes"; + } + case ".pbtxt": + { + return $"{assetName}.txt"; + } + default: + { + return $"{assetName}{extension}"; + } + } + } + } +} diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceUtil.cs.meta b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceUtil.cs.meta new file mode 100644 index 000000000..dfc8ac9fa --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Util/ResourceUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eba4ddb55310ce901800af4641131016 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Tasks/Audio/AudioClassifier/AudioClassifierTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Tasks/Audio/AudioClassifier/AudioClassifierTest.cs index ed50e4de5..09437250b 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Tasks/Audio/AudioClassifier/AudioClassifierTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Tasks/Audio/AudioClassifier/AudioClassifierTest.cs @@ -1,15 +1,22 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + using System; using System.Collections; using System.Collections.Generic; +using System.Text.RegularExpressions; using NUnit.Framework; +using Mediapipe.Tasks.Components.Containers; using Mediapipe.Tasks.Core; using Mediapipe.Tasks.Audio.Core; using Mediapipe.Tasks.Audio.AudioClassifier; +using Mediapipe.Unity; using UnityEditor; using UnityEngine; using UnityEngine.TestTools; -using System.Text.RegularExpressions; -using Mediapipe.Tasks.Components.Containers; using Stopwatch = System.Diagnostics.Stopwatch; @@ -22,7 +29,7 @@ public class AudioClassifierTest private const int _CallbackTimeoutMillisec = 1000; - // private static readonly ResourceManager _ResourceManager = new LocalResourceManager(); + private static readonly IResourceManager _ResourceManager = new LocalResourceManager(); private readonly Lazy _audioClassifierModel = new Lazy(() => AssetDatabase.LoadAssetAtPath($"{_ResourcePath}/yamnet_audio_classifier_with_metadata.bytes")); @@ -55,12 +62,12 @@ public void Create_ShouldReturnAudioClassifier_When_AssetModelBufferIsValid() }); } - [Test, Ignore("TODO: enable to initialize ResourceManager twice")] + [Test] public void Create_ShouldThrowBadStatusException_When_AssetModelPathDoesNotExist() { var options = new AudioClassifierOptions(new BaseOptions(BaseOptions.Delegate.CPU, modelAssetPath: "unknown_path.bytes")); - LogAssert.Expect(LogType.Exception, new Regex("FileNotFoundException")); + LogAssert.Expect(LogType.Exception, new Regex("KeyNotFoundException")); _ = Assert.Throws(() => { @@ -68,11 +75,10 @@ public void Create_ShouldThrowBadStatusException_When_AssetModelPathDoesNotExist }); } - [UnityTest, Ignore("TODO: enable to initialize ResourceManager twice")] + [UnityTest] public IEnumerator Create_ShouldReturnAudioClassifier_When_AssetModelPathIsValid() { - // yield return _ResourceManager.PrepareAssetAsync("yamnet_audio_classifier_with_metadata.bytes"); - yield return null; + yield return _ResourceManager.PrepareAssetAsync("yamnet_audio_classifier_with_metadata.bytes"); var options = new AudioClassifierOptions(new BaseOptions(BaseOptions.Delegate.CPU, modelAssetPath: "yamnet_audio_classifier_with_metadata.bytes")); diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Tasks/Vision/FaceDetector/FaceDetectorTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Tasks/Vision/FaceDetector/FaceDetectorTest.cs index 326c8687d..63ece75ab 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Tasks/Vision/FaceDetector/FaceDetectorTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Tasks/Vision/FaceDetector/FaceDetectorTest.cs @@ -1,15 +1,22 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + using System; using System.Collections; +using System.Text.RegularExpressions; using NUnit.Framework; +using Mediapipe.Tasks.Components.Containers; using Mediapipe.Tasks.Core; using Mediapipe.Tasks.Vision.Core; using Mediapipe.Tasks.Vision.FaceDetector; +using Mediapipe.Unity; using Unity.Collections; using UnityEditor; using UnityEngine; using UnityEngine.TestTools; -using System.Text.RegularExpressions; -using Mediapipe.Tasks.Components.Containers; using Stopwatch = System.Diagnostics.Stopwatch; @@ -22,7 +29,7 @@ public class FaceDetectorTest private const int _CallbackTimeoutMillisec = 1000; - // private static readonly ResourceManager _ResourceManager = new LocalResourceManager(); + private static readonly IResourceManager _ResourceManager = new LocalResourceManager(); private readonly Lazy _faceDetectorModel = new Lazy(() => AssetDatabase.LoadAssetAtPath($"{_ResourcePath}/blaze_face_short_range.bytes")); @@ -55,12 +62,12 @@ public void Create_ShouldReturnFaceDetector_When_AssetModelBufferIsValid() }); } - [Test, Ignore("TODO: enable to initialize ResourceManager twice")] + [Test] public void Create_ShouldThrowBadStatusException_When_AssetModelPathDoesNotExist() { var options = new FaceDetectorOptions(new BaseOptions(BaseOptions.Delegate.CPU, modelAssetPath: "unknown_path.bytes")); - LogAssert.Expect(LogType.Exception, new Regex("FileNotFoundException")); + LogAssert.Expect(LogType.Exception, new Regex("KeyNotFoundException")); _ = Assert.Throws(() => { @@ -68,11 +75,10 @@ public void Create_ShouldThrowBadStatusException_When_AssetModelPathDoesNotExist }); } - [UnityTest, Ignore("TODO: enable to initialize ResourceManager twice")] + [UnityTest] public IEnumerator Create_returns_FaceLandmarker_when_assetModelPath_is_valid() { - // yield return _ResourceManager.PrepareAssetAsync("blaze_face_short_range.bytes"); - yield return null; + yield return _ResourceManager.PrepareAssetAsync("blaze_face_short_range.bytes"); var options = new FaceDetectorOptions(new BaseOptions(BaseOptions.Delegate.CPU, modelAssetPath: "blaze_face_short_range.bytes"));