diff --git a/CHANGELOG.md b/CHANGELOG.md index 81c85b2..c345b8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ All package updates & migration steps will be listed in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.5.0] - 2025-03-18 +### Added +- `InfoExists` and `HasAssignedValue` getters added to the `ParameterReference` +- Support for `AssetReferenceGameObject` +- Versioning for code gen. +- Support to pass in infos to the `Error` and `Warn` methods in validators. +### Fixed +- Unclear error message when trying to set an incorrect scriptable object by name in a csv. + ## [4.4.0] - 2025-03-11 ### Added - Support for circular references of structs if using a `IReadOnlyList` diff --git a/Editor/Common/PropertyTypes/AssetReferenceGameObjectListPropertyType.cs b/Editor/Common/PropertyTypes/AssetReferenceGameObjectListPropertyType.cs new file mode 100644 index 0000000..2465e65 --- /dev/null +++ b/Editor/Common/PropertyTypes/AssetReferenceGameObjectListPropertyType.cs @@ -0,0 +1,16 @@ +#if ADDRESSABLE_PARAMS +using System.Reflection; +using UnityEngine.AddressableAssets; + +namespace PocketGems.Parameters.Common.PropertyTypes.Editor +{ + internal class AssetReferenceGameObjectListPropertyType : AssetReferenceListPropertyType + { + public AssetReferenceGameObjectListPropertyType(PropertyInfo propertyInfo) : base(propertyInfo) + { + } + + protected override string ClassName => nameof(AssetReferenceGameObject); + } +} +#endif diff --git a/Editor/Common/PropertyTypes/AssetReferenceGameObjectListPropertyType.cs.meta b/Editor/Common/PropertyTypes/AssetReferenceGameObjectListPropertyType.cs.meta new file mode 100644 index 0000000..e8c08d0 --- /dev/null +++ b/Editor/Common/PropertyTypes/AssetReferenceGameObjectListPropertyType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f5c4767972e44195b5eb0556066039c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Common/PropertyTypes/AssetReferenceGameObjectPropertyType.cs b/Editor/Common/PropertyTypes/AssetReferenceGameObjectPropertyType.cs new file mode 100644 index 0000000..89ad8d9 --- /dev/null +++ b/Editor/Common/PropertyTypes/AssetReferenceGameObjectPropertyType.cs @@ -0,0 +1,16 @@ +#if ADDRESSABLE_PARAMS +using System.Reflection; +using UnityEngine.AddressableAssets; + +namespace PocketGems.Parameters.Common.PropertyTypes.Editor +{ + internal class AssetReferenceGameObjectPropertyType : AssetReferencePropertyType + { + public AssetReferenceGameObjectPropertyType(PropertyInfo propertyInfo) : base(propertyInfo) + { + } + + protected override string ClassName => nameof(AssetReferenceGameObject); + } +} +#endif diff --git a/Editor/Common/PropertyTypes/AssetReferenceGameObjectPropertyType.cs.meta b/Editor/Common/PropertyTypes/AssetReferenceGameObjectPropertyType.cs.meta new file mode 100644 index 0000000..5fa3d43 --- /dev/null +++ b/Editor/Common/PropertyTypes/AssetReferenceGameObjectPropertyType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4f7771b087ff4c039d93857fa31bc38 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Common/PropertyTypes/PropertyTypeFactory.cs b/Editor/Common/PropertyTypes/PropertyTypeFactory.cs index 6e06e12..e147b57 100644 --- a/Editor/Common/PropertyTypes/PropertyTypeFactory.cs +++ b/Editor/Common/PropertyTypes/PropertyTypeFactory.cs @@ -136,6 +136,10 @@ public static IPropertyType Create(IParameterInterface parameterInterface, Prope return new AssetReferencePropertyType(propertyInfo); if (propertyType == typeof(IReadOnlyList)) return new AssetReferenceListPropertyType(propertyInfo); + if (propertyType == typeof(AssetReferenceGameObject)) + return new AssetReferenceGameObjectPropertyType(propertyInfo); + if (propertyType == typeof(IReadOnlyList)) + return new AssetReferenceGameObjectListPropertyType(propertyInfo); if (propertyType == typeof(AssetReferenceSprite)) return new AssetReferenceSpritePropertyType(propertyInfo); if (propertyType == typeof(IReadOnlyList)) diff --git a/README/InterfacesAndEnums.md b/README/InterfacesAndEnums.md index 00c1c28..ac8b6be 100644 --- a/README/InterfacesAndEnums.md +++ b/README/InterfacesAndEnums.md @@ -245,9 +245,11 @@ IReadOnlyList> Rewards { get; } Addressable asset & sprite references are supported if the [`com.unity.addressables`](https://docs.unity3d.com/Packages/com.unity.addressables@latest/index.html) package is added to the Unity project. ```C# AssetReference WorldItemPrefab { get; } +AssetReferenceGameObject Node { get; } AssetReferenceSprite Icon { get; } AssetReferenceAtlasedSprite Image { get; } IReadOnlyList Doobers { get; } +IReadOnlyList Nodes { get; } IReadOnlyList LoadingImages { get; } IReadOnlyList Images { get; } ``` diff --git a/Runtime/LocalCSV/CSVValueConverter.cs b/Runtime/LocalCSV/CSVValueConverter.cs index 4b70dbf..dcbef36 100644 --- a/Runtime/LocalCSV/CSVValueConverter.cs +++ b/Runtime/LocalCSV/CSVValueConverter.cs @@ -248,7 +248,7 @@ public static ParameterReference FromString(string value) if (ScriptableObjectLookupCache.Enabled) { var data = ScriptableObjectLookupCache.LookUp(value); - for (int i = 0; i < data.Count; i++) + for (int i = 0; i < data?.Count; i++) { var path = data[i].Item2; var asset = AssetDatabase.LoadAssetAtPath(path); diff --git a/Runtime/LocalCSV/CSVValueConverter_Addressable.cs b/Runtime/LocalCSV/CSVValueConverter_Addressable.cs index 691bbf0..61d4d08 100644 --- a/Runtime/LocalCSV/CSVValueConverter_Addressable.cs +++ b/Runtime/LocalCSV/CSVValueConverter_Addressable.cs @@ -60,6 +60,24 @@ public static UnityEngine.AddressableAssets.AssetReference FromString(string val } } + public static class AssetReferenceGameObject + { + public static string ToString(UnityEngine.AddressableAssets.AssetReferenceGameObject value) + { + return AssetReference.ToString(value); + } + + public static UnityEngine.AddressableAssets.AssetReferenceGameObject FromString(string value, + bool validateGuid = false) + { + (string guid, string subObjectName) = AssetReference.ParseString(value, validateGuid); + var reference = new UnityEngine.AddressableAssets.AssetReferenceGameObject(guid); + if (subObjectName != null) + reference.SubObjectName = subObjectName; + return reference; + } + } + public static class AssetReferenceSprite { public static string ToString(UnityEngine.AddressableAssets.AssetReferenceSprite value) @@ -120,6 +138,32 @@ public static UnityEngine.AddressableAssets.AssetReference[] FromString(string v } } + public static class AssetReferenceGameObjectArray + { + public static string ToString(UnityEngine.AddressableAssets.AssetReferenceGameObject[] value) + { + if (value == null) + return ""; + var guids = new string[value.Length]; + for (int i = 0; i < value.Length; i++) + guids[i] = AssetReferenceGameObject.ToString(value[i]); + return string.Join(ListDelimiter.ToString(), guids); + } + + public static UnityEngine.AddressableAssets.AssetReferenceGameObject[] FromString(string value, + bool validateGuid = false) + { + // must return a non null value so we can detect overriding of properties by checking non null + if (string.IsNullOrWhiteSpace(value)) + return Array.Empty(); + var guids = value.Split(ListDelimiter); + var assetRefs = new UnityEngine.AddressableAssets.AssetReferenceGameObject[guids.Length]; + for (int i = 0; i < guids.Length; i++) + assetRefs[i] = AssetReferenceGameObject.FromString(guids[i], validateGuid); + return assetRefs; + } + } + public static class AssetReferenceSpriteArray { public static string ToString(UnityEngine.AddressableAssets.AssetReferenceSprite[] value) diff --git a/Runtime/ParameterReference.cs b/Runtime/ParameterReference.cs index d4030ad..41db739 100644 --- a/Runtime/ParameterReference.cs +++ b/Runtime/ParameterReference.cs @@ -12,13 +12,16 @@ namespace PocketGems.Parameters public abstract class ParameterReference { [SerializeField] protected string guid; + [NonSerialized] protected string _identifier; /// - /// Identifier is only set at runtime (abtesting) and not serialized in the editor. + /// The assigned guid that is set typically from in the editor or when loaded from the parameter manager. /// - [NonSerialized] protected string _identifier; - public string AssignedGUID => guid; + + /// + /// Identifier is only set at runtime (abtesting) and not serialized in the editor. + /// public string AssignedIdentifier => _identifier; /// @@ -82,6 +85,9 @@ public int CompareTo(ParameterReference other) return string.Compare(info.Identifier, otherInfo.Identifier); } + /// + /// A getter return the parameter info. Null if it doesn't exist. + /// public T Info { get @@ -104,6 +110,26 @@ public T Info } } + /// + /// Returns true if an info exists for the reference. + /// + /// A ParameterReference could have HasAssignedValue be true but InfoExists return false. + /// This could happen if the assigned guid/identifier doesn't exist in the ParameterManager + /// due to an incorrect assignment (validation wasn't ran or the identifier was assigned at + /// runtime and incorrect). + /// + public bool InfoExists => Info != null; + + /// + /// True if this reference has been assigned a guid/identifier that might exist. + /// + /// A ParameterReference could have HasAssignedValue be true but InfoExists return false. + /// This could happen if the assigned guid/identifier doesn't exist in the ParameterManager + /// due to an incorrect assignment (validation wasn't ran or the identifier was assigned at + /// runtime and incorrect). + /// + public bool HasAssignedValue => !string.IsNullOrWhiteSpace(guid) || !string.IsNullOrWhiteSpace(_identifier); + internal T GetInfo(IParameterManager parameterManager) { // parameterManager.GetWithGUID will throw a LogError if it doesn't exist since diff --git a/Runtime/Validation/BaseDataValidator.cs b/Runtime/Validation/BaseDataValidator.cs index 444d196..842a9c6 100644 --- a/Runtime/Validation/BaseDataValidator.cs +++ b/Runtime/Validation/BaseDataValidator.cs @@ -29,6 +29,18 @@ public abstract class BaseDataValidator : ITypedDataValidator where T : cl /// parameter manager to query if needed during validation protected abstract void ValidateParameters(IParameterManager parameterManager); + /// + /// Log an error during validation. + /// + /// the info with the issue + /// property name with the error + /// user facing message about the error + protected void Error(T info, string propertyName, string message) + { + var error = new ValidationError(typeof(T), info.Identifier, propertyName, message); + _errors.Add(error); + } + /// /// Log an error during validation. /// @@ -40,6 +52,17 @@ protected void Error(string propertyName, string message) _errors.Add(error); } + /// + /// Log an error during validation. + /// + /// the info with the issue + /// user facing message about the error + protected void Error(T info, string message) + { + var error = new ValidationError(typeof(T), info.Identifier, null, message); + _errors.Add(error); + } + /// /// General error during validation. /// @@ -50,6 +73,19 @@ protected void Error(string message) _errors.Add(error); } + /// + /// Log a warning during validation. + /// + /// the info with the issue + /// property name with the warning + /// user facing message about the warning + protected void Warn(T info, string propertyName, string message) + { + var error = new ValidationError(typeof(T), info.Identifier, propertyName, message, + severity: ValidationError.Severity.Warning); + _errors.Add(error); + } + /// /// Log a warning during validation. /// @@ -62,6 +98,18 @@ protected void Warn(string propertyName, string message) _errors.Add(error); } + /// + /// General warning during validation. + /// + /// the info with the issue + /// user facing message about the warning + protected void Warn(T info, string message) + { + var error = new ValidationError(typeof(T), info.Identifier, null, message, + severity: ValidationError.Severity.Warning); + _errors.Add(error); + } + /// /// General warning during validation. /// diff --git a/Tests/Editor/Common/PropertyTypes/PropertyTypesTest.cs b/Tests/Editor/Common/PropertyTypes/PropertyTypesTest.cs index 9b1124a..85f44ba 100644 --- a/Tests/Editor/Common/PropertyTypes/PropertyTypesTest.cs +++ b/Tests/Editor/Common/PropertyTypes/PropertyTypesTest.cs @@ -86,9 +86,11 @@ private interface ITestInfo : IBaseInfo #if ADDRESSABLE_PARAMS AssetReference MyAsset { get; } + AssetReferenceGameObject MyGameObject { get; } AssetReferenceSprite MyAssetSprite { get; } AssetReferenceAtlasedSprite MyAssetAltasdSprite { get; } IReadOnlyList MyAssets { get; } + IReadOnlyList MyGameObjects { get; } IReadOnlyList MyAssetSprites { get; } IReadOnlyList MyAssetAltasdSprites { get; } #endif @@ -228,9 +230,11 @@ public void ValidateIdentifier() [TestCase(nameof(ITestInfo.MyStructs))] #if ADDRESSABLE_PARAMS [TestCase(nameof(ITestInfo.MyAsset))] + [TestCase(nameof(ITestInfo.MyGameObject))] [TestCase(nameof(ITestInfo.MyAssetSprite))] [TestCase(nameof(ITestInfo.MyAssetAltasdSprite))] [TestCase(nameof(ITestInfo.MyAssets))] + [TestCase(nameof(ITestInfo.MyGameObjects))] [TestCase(nameof(ITestInfo.MyAssetSprites))] [TestCase(nameof(ITestInfo.MyAssetAltasdSprites))] #endif diff --git a/Tests/Runtime/LocalCSV/CSVValueConversionTest_Addressable.cs b/Tests/Runtime/LocalCSV/CSVValueConversionTest_Addressable.cs index 389af0f..166c269 100644 --- a/Tests/Runtime/LocalCSV/CSVValueConversionTest_Addressable.cs +++ b/Tests/Runtime/LocalCSV/CSVValueConversionTest_Addressable.cs @@ -41,12 +41,6 @@ public void AssetReferenceFromString(string value, string expectedGUID, string e Assert.AreEqual(expectedSubObjectName, reference.SubObjectName); } - [Test] - public void AssetReferenceFromStringError() - { - Assert.Throws(() => CSVValueConverter.AssetReference.FromString("asdf")); - } - [Test] [TestCase("blah", "objName", "blah-objName")] [TestCase("blah", "objName-", "blah-objName-")] @@ -54,16 +48,37 @@ public void AssetReferenceFromStringError() [TestCase("blah", null, "blah-")] [TestCase("", null, "-")] [TestCase(null, null, "-")] - public void AssetReferenceSpriteToString(string guid, string subObjectName, string expected) + public void AssetReferenceGameObjectToString(string guid, string subObjectName, string expected) { - var reference = new AssetReferenceSprite(guid); + var reference = new AssetReferenceGameObject(guid); if (subObjectName != null) reference.SubObjectName = subObjectName; - Assert.AreEqual(expected, CSVValueConverter.AssetReferenceSprite.ToString(reference)); + Assert.AreEqual(expected, CSVValueConverter.AssetReferenceGameObject.ToString(reference)); if (guid == null) - Assert.AreEqual(expected, CSVValueConverter.AssetReferenceSprite.ToString(null)); + Assert.AreEqual(expected, CSVValueConverter.AssetReferenceGameObject.ToString(null)); + } + + [Test] + [TestCase("blah-", "blah", null)] + [TestCase("blah-boo", "blah", "boo")] + [TestCase("blah-boo-", "blah", "boo-")] + [TestCase("", "", null)] + [TestCase(null, "", null)] + public void AssetReferenceGameObjectFromString(string value, string expectedGUID, string expectedSubObjectName) + { + var reference = CSVValueConverter.AssetReferenceGameObject.FromString(value); + Assert.IsNotNull(reference); + Assert.AreEqual(typeof(AssetReferenceGameObject), reference.GetType()); + Assert.AreEqual(expectedGUID, reference.AssetGUID); + Assert.AreEqual(expectedSubObjectName, reference.SubObjectName); + } + + [Test] + public void AssetReferenceFromStringError() + { + Assert.Throws(() => CSVValueConverter.AssetReference.FromString("asdf")); } [Test] @@ -73,16 +88,16 @@ public void AssetReferenceSpriteToString(string guid, string subObjectName, stri [TestCase("blah", null, "blah-")] [TestCase("", null, "-")] [TestCase(null, null, "-")] - public void AssetReferenceAtlasedSpriteToString(string guid, string subObjectName, string expected) + public void AssetReferenceSpriteToString(string guid, string subObjectName, string expected) { - var reference = new AssetReferenceAtlasedSprite(guid); + var reference = new AssetReferenceSprite(guid); if (subObjectName != null) reference.SubObjectName = subObjectName; - Assert.AreEqual(expected, CSVValueConverter.AssetReferenceAtlasedSprite.ToString(reference)); + Assert.AreEqual(expected, CSVValueConverter.AssetReferenceSprite.ToString(reference)); if (guid == null) - Assert.AreEqual(expected, CSVValueConverter.AssetReferenceAtlasedSprite.ToString(null)); + Assert.AreEqual(expected, CSVValueConverter.AssetReferenceSprite.ToString(null)); } [Test] @@ -100,6 +115,25 @@ public void AssetReferenceSpriteFromString(string value, string expectedGUID, st Assert.AreEqual(expectedSubObjectName, reference.SubObjectName); } + [Test] + [TestCase("blah", "objName", "blah-objName")] + [TestCase("blah", "objName-", "blah-objName-")] + [TestCase("blah", "", "blah-")] + [TestCase("blah", null, "blah-")] + [TestCase("", null, "-")] + [TestCase(null, null, "-")] + public void AssetReferenceAtlasedSpriteToString(string guid, string subObjectName, string expected) + { + var reference = new AssetReferenceAtlasedSprite(guid); + if (subObjectName != null) + reference.SubObjectName = subObjectName; + + Assert.AreEqual(expected, CSVValueConverter.AssetReferenceAtlasedSprite.ToString(reference)); + + if (guid == null) + Assert.AreEqual(expected, CSVValueConverter.AssetReferenceAtlasedSprite.ToString(null)); + } + [Test] [TestCase("blah-", "blah", null)] [TestCase("blah-boo", "blah", "boo")] @@ -152,6 +186,46 @@ public void AssetReferenceArrayFromString() Assert.AreEqual("sub", result[3].SubObjectName); } + [Test] + public void AssetReferenceGameObjectArrayToString() + { + void Test(string expected, AssetReferenceGameObject[] value) + { + Assert.AreEqual(expected, CSVValueConverter.AssetReferenceGameObjectArray.ToString(value)); + } + + var refNormal1 = new AssetReferenceGameObject("guid1"); + var refNormal2 = new AssetReferenceGameObject("guid2"); + refNormal2.SubObjectName = "sub"; + var refNull = new AssetReferenceGameObject(null); + var refEmpty = new AssetReferenceGameObject(""); + + Test("", null); + Test("guid1-", new[] { refNormal1 }); + Test("guid1-|-", new[] { refNormal1, refNull }); + Test("guid1-|-|-|guid2-sub", new[] { refNormal1, refNull, refEmpty, refNormal2 }); + } + + [Test] + public void AssetReferenceGameObjectArrayFromString() + { + Assert.AreEqual(Array.Empty(), + CSVValueConverter.AssetReferenceGameObjectArray.FromString(null)); + Assert.AreEqual(Array.Empty(), + CSVValueConverter.AssetReferenceGameObjectArray.FromString("")); + Assert.AreEqual(Array.Empty(), + CSVValueConverter.AssetReferenceGameObjectArray.FromString(" ")); + var result = CSVValueConverter.AssetReferenceGameObjectArray.FromString("guid-|-|-|guid2-sub"); + Assert.AreEqual("guid", result[0].AssetGUID); + Assert.AreEqual(null, result[0].SubObjectName); + Assert.AreEqual("", result[1].AssetGUID); + Assert.AreEqual(null, result[1].SubObjectName); + Assert.AreEqual("", result[2].AssetGUID); + Assert.AreEqual(null, result[2].SubObjectName); + Assert.AreEqual("guid2", result[3].AssetGUID); + Assert.AreEqual("sub", result[3].SubObjectName); + } + [Test] public void AssetReferenceSpriteArrayToString() { diff --git a/Tests/Runtime/ParameterReferenceTest.cs b/Tests/Runtime/ParameterReferenceTest.cs index aa8d1a6..1e3eacd 100644 --- a/Tests/Runtime/ParameterReferenceTest.cs +++ b/Tests/Runtime/ParameterReferenceTest.cs @@ -41,47 +41,47 @@ public void TearDown() public void Init() { var parameterReference = new ParameterReference(); - Assert.IsNull(parameterReference.AssignedGUID); - Assert.IsNull(parameterReference.AssignedIdentifier); - Assert.IsNotEmpty(parameterReference.ToString()); + Assert.That(parameterReference.AssignedGUID, Is.Null); + Assert.That(parameterReference.AssignedIdentifier, Is.Null); + Assert.That(parameterReference.ToString(), Is.Not.Empty); parameterReference = new ParameterReference(kTestGuid); - Assert.AreEqual(kTestGuid, parameterReference.AssignedGUID); - Assert.IsNull(parameterReference.AssignedIdentifier); - Assert.IsNotEmpty(parameterReference.ToString()); + Assert.That(parameterReference.AssignedGUID, Is.EqualTo(kTestGuid)); + Assert.That(parameterReference.AssignedIdentifier, Is.Null); + Assert.That(parameterReference.ToString(), Is.Not.Empty); parameterReference = new ParameterReference(kTestIdentifier, true); - Assert.IsNull(parameterReference.AssignedGUID); - Assert.AreEqual(kTestIdentifier, parameterReference.AssignedIdentifier); - Assert.IsNotEmpty(parameterReference.ToString()); + Assert.That(parameterReference.AssignedGUID, Is.Null); + Assert.That(parameterReference.AssignedIdentifier, Is.EqualTo(kTestIdentifier)); + Assert.That(parameterReference.ToString(), Is.Not.Empty); } [Test] public void GetByGuid() { var parameterReference = new ParameterReference(kTestGuid); - Assert.AreEqual(_mockInfo, parameterReference.Info); + Assert.That(parameterReference.Info, Is.EqualTo(_mockInfo)); } [Test] public void GetByIdentifier() { var parameterReference = new ParameterReference(kTestIdentifier, true); - Assert.AreEqual(_mockInfo, parameterReference.Info); + Assert.That(parameterReference.Info, Is.EqualTo(_mockInfo)); } [Test] public void GetNothing() { var parameterReference = new ParameterReference(); - Assert.IsNull(parameterReference.Info); + Assert.That(parameterReference.Info, Is.Null); } [Test] public void MissingGuidInParameterManager() { var parameterReference = new ParameterReference("bad guid"); - Assert.IsNull(parameterReference.Info); + Assert.That(parameterReference.Info, Is.Null); } [Test] @@ -89,7 +89,7 @@ public void MissingIdentifierInParameterManager() { var parameterReference = new ParameterReference("bad id", true); LogAssert.Expect(LogType.Error, new Regex("Cannot find.*")); - Assert.IsNull(parameterReference.Info); + Assert.That(parameterReference.Info, Is.Null); } [Test] @@ -101,15 +101,15 @@ public void NonExistentParameterManager() var parameterReference = new ParameterReference(kTestGuid); LogAssert.Expect(LogType.Error, errorString); - Assert.IsNull(parameterReference.Info); + Assert.That(parameterReference.Info, Is.Null); LogAssert.Expect(LogType.Error, errorString); - Assert.IsNotEmpty(parameterReference.ToString()); + Assert.That(parameterReference.ToString(), Is.Not.Empty); parameterReference = new ParameterReference(kTestIdentifier, true); LogAssert.Expect(LogType.Error, errorString); - Assert.IsNull(parameterReference.Info); + Assert.That(parameterReference.Info, Is.Null); LogAssert.Expect(LogType.Error, errorString); - Assert.IsNotEmpty(parameterReference.ToString()); + Assert.That(parameterReference.ToString(), Is.Not.Empty); } [Test] @@ -125,13 +125,13 @@ ParameterReference CreateReference(string guid, string identifier, bo Assert.AreEqual(identifier, reference.Info.Identifier); if (refIsIdentifier) { - Assert.IsNull(reference.AssignedGUID); - Assert.AreEqual(identifier, reference.AssignedIdentifier); + Assert.That(reference.AssignedGUID, Is.Null); + Assert.That(reference.AssignedIdentifier, Is.EqualTo(identifier)); } else { - Assert.AreEqual(guid, reference.AssignedGUID); - Assert.IsNull(reference.AssignedIdentifier); + Assert.That(reference.AssignedGUID, Is.EqualTo(guid)); + Assert.That(reference.AssignedIdentifier, Is.Null); } return reference; } @@ -145,11 +145,11 @@ ParameterReference CreateReference(string guid, string identifier, bo refList.Sort(); // sorted by identifier - Assert.AreEqual(refNull, refList[0]); - Assert.AreEqual(refA, refList[1]); - Assert.AreEqual(refB, refList[2]); - Assert.AreEqual(refC, refList[3]); - Assert.AreEqual(refD, refList[4]); + Assert.That(refList[0], Is.EqualTo(refNull)); + Assert.That(refList[1], Is.EqualTo(refA)); + Assert.That(refList[2], Is.EqualTo(refB)); + Assert.That(refList[3], Is.EqualTo(refC)); + Assert.That(refList[4], Is.EqualTo(refD)); var ref1_1 = CreateReference("abc", "1", true); var ref1_2 = CreateReference("abc", "1", true); @@ -161,12 +161,30 @@ ParameterReference CreateReference(string guid, string identifier, bo for (int j = 0; j < ref1List.Count; j++) { // verify all of these combinations are equal - Assert.AreEqual(0, ref1List[i].CompareTo(ref1List[j])); + Assert.That(ref1List[i].CompareTo(ref1List[j]), Is.Zero); } } // two nulls are equal - Assert.AreEqual(0, refNull.CompareTo(new ParameterReference())); + Assert.That(refNull.CompareTo(new ParameterReference()), Is.Zero); + } + + [Test] + [TestCase(null, false, false, false)] + [TestCase(null, true, false, false)] + [TestCase("", false, false, false)] + [TestCase("", true, false, false)] + [TestCase(kTestGuid, false, true, true)] + [TestCase("blah", false, true, false)] + [TestCase(kTestIdentifier, true, true, true)] + [TestCase("blah", true, true, false)] + public void InfoExists_HasAssignedValue(string value, bool isIdentifier, bool expectedHasAssignedValue, bool expectedInfoExists) + { + var parameterReference = new ParameterReference(value, isIdentifier); + Assert.That(parameterReference.HasAssignedValue, Is.EqualTo(expectedHasAssignedValue)); + if (isIdentifier && expectedHasAssignedValue && !expectedInfoExists) + LogAssert.Expect(LogType.Error, new Regex("Cannot find info of type .*")); + Assert.That(parameterReference.InfoExists, Is.EqualTo(expectedInfoExists)); } } } diff --git a/Tests/Runtime/TestCode/TestBaseDataValidator.cs b/Tests/Runtime/TestCode/TestBaseDataValidator.cs index 0492696..baefe9a 100644 --- a/Tests/Runtime/TestCode/TestBaseDataValidator.cs +++ b/Tests/Runtime/TestCode/TestBaseDataValidator.cs @@ -4,11 +4,15 @@ namespace PocketGems.Parameters.Validation { public class TestBaseDataValidator : BaseDataValidator where T : class, IBaseInfo { + public const string InfoIdentifier = "some id"; + public const string PropertyName = "some property name"; public const string ErrorMessage1 = "some error"; public const string ErrorMessage2 = "some other error"; + public const string ErrorMessage3 = "some other other error"; public const string WarningMessage1 = "some warning"; public const string WarningMessage2 = "some other warning"; + public const string WarningMessage3 = "some other other warning"; protected override void ValidateInfo(IParameterManager parameterManager, T info) { @@ -19,7 +23,13 @@ protected override void ValidateInfo(IParameterManager parameterManager, T info) protected override void ValidateParameters(IParameterManager parameterManager) { Error(ErrorMessage2); + var info = parameterManager.Get(InfoIdentifier); + Error(info, PropertyName, ErrorMessage3); + Error(info, ErrorMessage3); + Warn(WarningMessage2); + Warn(info, PropertyName, WarningMessage3); + Warn(info, WarningMessage3); } } } diff --git a/Tests/Runtime/Validation/BaseDataValidatorTest.cs b/Tests/Runtime/Validation/BaseDataValidatorTest.cs index 6a375b6..d6504fc 100644 --- a/Tests/Runtime/Validation/BaseDataValidatorTest.cs +++ b/Tests/Runtime/Validation/BaseDataValidatorTest.cs @@ -5,56 +5,96 @@ namespace PocketGems.Parameters.Validation { public class BaseDataValidatorTest { + private IMySpecialInfo _mockInfo; + private IParameterManager _mockParameterManager; + + private IDataValidator _validator; + + [SetUp] + public void SetUp() + { + _mockInfo = Substitute.For(); + _mockInfo.Identifier.Returns(TestBaseDataValidator.InfoIdentifier); + + _mockParameterManager = Substitute.For(); + _mockParameterManager.Get(_mockInfo.Identifier).Returns(_mockInfo); + + _validator = new TestBaseDataValidator(); + } + [Test] public void ValidateInfo() { - const string infoIdentifier = "some id"; - - var mock = Substitute.For(); - mock.Identifier.Returns(infoIdentifier); - IDataValidator validator = new TestBaseDataValidator(); - validator.ValidateInfo(null, mock); + _validator.ValidateInfo(_mockParameterManager, _mockInfo); - var errors = validator.Errors; - Assert.AreEqual(2, errors.Count); + var errors = _validator.Errors; + Assert.That(errors.Count, Is.EqualTo(2)); var error = errors[0]; - Assert.AreEqual(typeof(IMySpecialInfo), error.InfoType); - Assert.AreEqual(infoIdentifier, error.InfoIdentifier); - Assert.AreEqual(ValidationError.Severity.Error, error.ErrorSeverity); - Assert.AreEqual(TestBaseDataValidator.PropertyName, error.InfoProperty); - Assert.AreEqual(TestBaseDataValidator.ErrorMessage1, error.Message); + Assert.That(error.InfoType, Is.EqualTo(typeof(IMySpecialInfo))); + Assert.That(error.InfoIdentifier, Is.EqualTo(TestBaseDataValidator.InfoIdentifier)); + Assert.That(error.ErrorSeverity, Is.EqualTo(ValidationError.Severity.Error)); + Assert.That(error.InfoProperty, Is.EqualTo(TestBaseDataValidator.PropertyName)); + Assert.That(error.Message, Is.EqualTo(TestBaseDataValidator.ErrorMessage1)); var warning = errors[1]; - Assert.AreEqual(typeof(IMySpecialInfo), warning.InfoType); - Assert.AreEqual(infoIdentifier, warning.InfoIdentifier); - Assert.AreEqual(ValidationError.Severity.Warning, warning.ErrorSeverity); - Assert.AreEqual(TestBaseDataValidator.PropertyName, warning.InfoProperty); - Assert.AreEqual(TestBaseDataValidator.WarningMessage1, warning.Message); + Assert.That(warning.InfoType, Is.EqualTo(typeof(IMySpecialInfo))); + Assert.That(warning.InfoIdentifier, Is.EqualTo(TestBaseDataValidator.InfoIdentifier)); + Assert.That(warning.ErrorSeverity, Is.EqualTo(ValidationError.Severity.Warning)); + Assert.That(warning.InfoProperty, Is.EqualTo(TestBaseDataValidator.PropertyName)); + Assert.That(warning.Message, Is.EqualTo(TestBaseDataValidator.WarningMessage1)); } [Test] public void ValidateParameters() { IDataValidator validator = new TestBaseDataValidator(); - validator.ValidateParameters(null); + validator.ValidateParameters(_mockParameterManager); var errors = validator.Errors; - Assert.AreEqual(2, errors.Count); + Assert.That(errors.Count, Is.EqualTo(6)); - var error = errors[0]; - Assert.AreEqual(typeof(IMySpecialInfo), error.InfoType); - Assert.IsNull(error.InfoIdentifier); - Assert.IsNull(error.InfoProperty); - Assert.AreEqual(ValidationError.Severity.Error, error.ErrorSeverity); - Assert.AreEqual(TestBaseDataValidator.ErrorMessage2, error.Message); + var error1 = errors[0]; + Assert.That(error1.InfoType, Is.EqualTo(typeof(IMySpecialInfo))); + Assert.That(error1.InfoIdentifier, Is.Null); + Assert.That(error1.InfoProperty, Is.Null); + Assert.That(error1.ErrorSeverity, Is.EqualTo(ValidationError.Severity.Error)); + Assert.That(error1.Message, Is.EqualTo(TestBaseDataValidator.ErrorMessage2)); - var warning = errors[1]; - Assert.AreEqual(typeof(IMySpecialInfo), warning.InfoType); - Assert.IsNull(warning.InfoIdentifier); - Assert.IsNull(warning.InfoProperty); - Assert.AreEqual(ValidationError.Severity.Warning, warning.ErrorSeverity); - Assert.AreEqual(TestBaseDataValidator.WarningMessage2, warning.Message); + var error2 = errors[1]; + Assert.That(error2.InfoType, Is.EqualTo(typeof(IMySpecialInfo))); + Assert.That(error2.InfoIdentifier, Is.EqualTo(TestBaseDataValidator.InfoIdentifier)); + Assert.That(error2.InfoProperty, Is.EqualTo(TestBaseDataValidator.PropertyName)); + Assert.That(error2.ErrorSeverity, Is.EqualTo(ValidationError.Severity.Error)); + Assert.That(error2.Message, Is.EqualTo(TestBaseDataValidator.ErrorMessage3)); + + var error3 = errors[2]; + Assert.That(error3.InfoType, Is.EqualTo(typeof(IMySpecialInfo))); + Assert.That(error3.InfoIdentifier, Is.EqualTo(TestBaseDataValidator.InfoIdentifier)); + Assert.That(error3.InfoProperty, Is.Null); + Assert.That(error3.ErrorSeverity, Is.EqualTo(ValidationError.Severity.Error)); + Assert.That(error3.Message, Is.EqualTo(TestBaseDataValidator.ErrorMessage3)); + + var warning1 = errors[3]; + Assert.That(warning1.InfoType, Is.EqualTo(typeof(IMySpecialInfo))); + Assert.That(warning1.InfoIdentifier, Is.Null); + Assert.That(warning1.InfoProperty, Is.Null); + Assert.That(warning1.ErrorSeverity, Is.EqualTo(ValidationError.Severity.Warning)); + Assert.That(warning1.Message, Is.EqualTo(TestBaseDataValidator.WarningMessage2)); + + var warning2 = errors[4]; + Assert.That(warning2.InfoType, Is.EqualTo(typeof(IMySpecialInfo))); + Assert.That(warning2.InfoIdentifier, Is.EqualTo(TestBaseDataValidator.InfoIdentifier)); + Assert.That(warning2.InfoProperty, Is.EqualTo(TestBaseDataValidator.PropertyName)); + Assert.That(warning2.ErrorSeverity, Is.EqualTo(ValidationError.Severity.Warning)); + Assert.That(warning2.Message, Is.EqualTo(TestBaseDataValidator.WarningMessage3)); + + var warning3 = errors[5]; + Assert.That(warning3.InfoType, Is.EqualTo(typeof(IMySpecialInfo))); + Assert.That(warning3.InfoIdentifier, Is.EqualTo(TestBaseDataValidator.InfoIdentifier)); + Assert.That(warning3.InfoProperty, Is.Null); + Assert.That(warning3.ErrorSeverity, Is.EqualTo(ValidationError.Severity.Warning)); + Assert.That(warning3.Message, Is.EqualTo(TestBaseDataValidator.WarningMessage3)); } } } diff --git a/package.json b/package.json index e75d665..1695aa2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.pocketgems.scriptableobject.flatbuffer", - "version": "4.4.0", + "version": "4.5.0", "displayName": "Scriptable Object - FlatBuffer", "description": "Seamless syncing between Scriptable Objects and CSVs. Scriptable Object data built to Google FlatBuffers for optimal runtime loading & access.", "unity": "2021.3", @@ -16,6 +16,7 @@ "name": "Pocket Gems", "url": "https://www.pocketgems.com/" }, + "codegen": "0.0.1", "dependencies": { "com.unity.nuget.newtonsoft-json": "2.0.2", "com.unity.testtools.codecoverage": "1.2.4",