logo SERENITY
Game Systems Foundation
Search Results for

    Show / Hide Table of Contents

    Class LoggingProfileCreatorTests

    EditMode tests for LoggingProfileCreator. Every test targets fixture assets under a private temp folder via Input.OutputFolderPath (and, for the two sink settings, their explicit asset-path test seams) — the real project's own UnityConsoleLogSettings/UnityFileLogSettings/ UnityLogProfile assets under Assets/Serenity/Media/Logging/ are never mutated, so these tests stay hermetic regardless of what the project already ships.

    Inheritance
    object
    LoggingProfileCreatorTests
    Inherited Members
    object.ToString()
    object.Equals(object)
    object.Equals(object, object)
    object.ReferenceEquals(object, object)
    object.GetHashCode()
    object.GetType()
    object.MemberwiseClone()
    Namespace: Serenity.Logging.Tests.Editor.Builder
    Assembly: Serenity.Logging.Tests.Editor.dll
    Syntax
    public class LoggingProfileCreatorTests

    Constructors

    LoggingProfileCreatorTests()

    Declaration
    public LoggingProfileCreatorTests()

    Methods

    Create_ConsoleSinkDisabled_DoesNotCreateConsoleAsset()

    Declaration
    public void Create_ConsoleSinkDisabled_DoesNotCreateConsoleAsset()

    Create_ExistingAssetSeededOnEverySerializedField_RestoresThemAll()

    Field-by-field regression guard for the generic capture Create(Input) now rolls back through (transaction.TrackExistingAsset), replacing the three hand-rolled Existing*Snapshot classes this migration deleted. Targets the profile asset — the last of the four existing-asset restores this creator captures, and the one whose file-removed rollback trigger the rest of this suite already exercises. Writes a distinct value into EVERY serialized field of the real profile asset via reflection — not just the ones ApplyProfileFields happens to know about — forces the update run to fail via the same planted-and-deleted-file technique the other rollback tests use, and asserts every field comes back. Proves the capture covers whatever the type declares, not a hand-maintained field list a future field addition could silently outgrow.

    Declaration
    public void Create_ExistingAssetSeededOnEverySerializedField_RestoresThemAll()

    Create_ExistingAssetsAtSamePaths_UpdatesAllThreeInPlace()

    The Id is held constant across both runs deliberately: Console/File resolve by their explicit path (singletons), but the profile resolves by-Id-within-folder (see Create_ProfileIdChangedBetweenRuns_CreatesANewProfileAndLeavesTheOldOneUntouched()) — a changed Id is a different resolution key, not a rename, so this "update in place" scenario only makes sense with the same Id both times.

    Declaration
    public void Create_ExistingAssetsAtSamePaths_UpdatesAllThreeInPlace()

    Create_ExistingProfileHasHandAuthoredRoutes_PreservesThemAndWarns()

    Declaration
    public void Create_ExistingProfileHasHandAuthoredRoutes_PreservesThemAndWarns()

    Create_ExistingStructuredSettings_DoesNotRewriteTheTableOrCollectionName()

    Declaration
    public void Create_ExistingStructuredSettings_DoesNotRewriteTheTableOrCollectionName()

    Create_NewSinkAtExplicitPathInMissingFolder_CreatesThatFolderLazily()

    The discriminating counterpart to Create_UpdateRunAgainstExistingSinksAndProfile_DoesNotCreateTheOutputFolder(): a brand-new sink at an explicit path under a folder that does not exist yet must have that folder created lazily as part of resolving that one sink, via ResolveOrCreateAtPath<TSettings>(SettingsResolution<TSettings>, string, string, string, SerenityAssetCreationTransaction, out bool) — proving the folder is still ensured where an asset is actually written, now that the old unconditional Input.OutputFolderPath ensure is gone.

    Declaration
    public void Create_NewSinkAtExplicitPathInMissingFolder_CreatesThatFolderLazily()

    Create_ProfileFileRemovedBeforeSecondRun_RollsBackConsoleAndFileMutationsToo()

    Exercises the resolve-or-edit rollback path across the WHOLE multi-asset set: the console and file sink settings are mutated in memory first, then the profile's pre-persist disk check fails (its asset file was removed from disk after the first Create() call). Every mutation — including the two sink assets that succeeded before the profile step failed — must be rolled back to its pre-call value, not just the profile.

    Declaration
    public void Create_ProfileFileRemovedBeforeSecondRun_RollsBackConsoleAndFileMutationsToo()

    Create_ProfileIdChangedBetweenRuns_CreatesANewProfileAndLeavesTheOldOneUntouched()

    Documents the flip side of the by-Id-within-folder resolution deliberately used for UnityLogProfile (see the type doc on LoggingProfileCreator): a changed ProfileId is a different resolution key, so it creates a brand-new profile asset alongside the old one rather than renaming/updating it in place. Console and File, resolved by their explicit path, are unaffected by the Id change and still update in place.

    Declaration
    public void Create_ProfileIdChangedBetweenRuns_CreatesANewProfileAndLeavesTheOldOneUntouched()

    Create_RegisterAsAddressablesFalse_LeavesAddressablesUntouched()

    Declaration
    public void Create_RegisterAsAddressablesFalse_LeavesAddressablesUntouched()

    Create_ReplaceExistingBackendAtSameName_Succeeds_ProducesOneCleanAssetWithNewConfig()

    Enables the non-destructive "Replace Existing Backend" flow at the SAME asset name (rename-to-temp): the old structured backend is relocated, never destroyed, until the whole run succeeds. Also switches backend KIND (PlayerPrefs to Sqlite) to prove the replacement can be a different concrete type at the same path.

    Declaration
    public void Create_ReplaceExistingBackendAtSameName_Succeeds_ProducesOneCleanAssetWithNewConfig()

    Create_ReplaceExistingBackendAtSameName_ThenLaterStepFails_RestoresTheOriginalBackendIntact()

    The same-name counterpart of Create_StructuredBackendReplacedThenProfileFileRemoved_RollsBackStructuredSettingsAndBackend(): this time the replacement uses the SAME StructuredBackendAssetName as the original, exercising the rename-to-temp path (rather than the plain create-then-assign path a different name takes). Reuses the profile-file-delete trick to force a genuine later-stage failure — the profile step runs AFTER the structured backend replace.

    Declaration
    public void Create_ReplaceExistingBackendAtSameName_ThenLaterStepFails_RestoresTheOriginalBackendIntact()

    Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing()

    The create-path counterpart: a stale, cache-valid-but-disk-missing destination folder makes the very first UnityEditor.AssetDatabase.CreateAsset(UnityEngine.Object,System.String) call fail natively, forcing a rollback of a brand-new run before any of the three assets exist. Nothing must be left dangling — no asset, no Addressables entry.

    Declaration
    public void Create_StaleFolderCacheOnFreshCreation_RollsBackAndLeavesNothing()

    Create_StructuredBackendReplacedThenProfileFileRemoved_RollsBackStructuredSettingsAndBackend()

    Exercises the structured sink's rollback path: the settings asset is mutated and its backend is replaced in memory, then the profile's pre-persist disk check fails (mirrors Create_ProfileFileRemovedBeforeSecondRun_RollsBackConsoleAndFileMutationsToo()). Both the structured settings mutation AND the Backend reference must roll back — not just the newly-created replacement backend asset getting deleted.

    Declaration
    public void Create_StructuredBackendReplacedThenProfileFileRemoved_RollsBackStructuredSettingsAndBackend()

    Create_StructuredSinkDisabled_DoesNotCreateStructuredAsset()

    Declaration
    public void Create_StructuredSinkDisabled_DoesNotCreateStructuredAsset()

    Create_StructuredSinkEnabled_CreatesSettingsAndBackendWiredAndLabeled()

    Declaration
    public void Create_StructuredSinkEnabled_CreatesSettingsAndBackendWiredAndLabeled()

    Create_StructuredSinkWithInstanceId_SetsInstanceKeyDefaultLoggerKey()

    Declaration
    public void Create_StructuredSinkWithInstanceId_SetsInstanceKeyDefaultLoggerKey()

    Create_UnderAmbiguousMultipleExistingConsoleSettings_CreatesANewOneWithoutMutatingEitherExisting()

    The Create(Input) counterpart of the ambiguity test above, mirroring SystemConfigurationSettingsCreatorTests.Create_UnderAmbiguousMultipleExistingAssets_CreatesANewAssetWithoutMutatingEitherExisting. Ambiguity is a warning, never a blocking error, so Create must still succeed: it creates a brand-new THIRD console settings asset under the requested output folder rather than silently resolving onto (and mutating) either pre-existing ambiguous asset. File sink is disabled throughout to isolate the console-sink ambiguity from the file sink's own (independent) resolution.

    Declaration
    public void Create_UnderAmbiguousMultipleExistingConsoleSettings_CreatesANewOneWithoutMutatingEitherExisting()

    Create_UpdateRunAgainstExistingSinksAndProfile_DoesNotCreateTheOutputFolder()

    Regression lock for the folder-ensure simplification this change makes: Create(Input) no longer ensures Input.OutputFolderPath unconditionally up front — each asset now ensures its own folder lazily, only on its own create path. This scenario does NOT discriminate against the old bug by itself: Console/File resolve by an explicit path already inside Serenity.Logging.Tests.Editor.Builder.LoggingProfileCreatorTests.TempFolder (which SetUp() always creates), and the profile resolves by Id inside that same folder, so the old unconditional ensure was already a no-op here too. It still locks the invariant going forward: a pure update run against three already-resolved assets creates nothing and leaves no new subfolder.

    Declaration
    public void Create_UpdateRunAgainstExistingSinksAndProfile_DoesNotCreateTheOutputFolder()

    Create_ValidInput_CreatesAllThreeAssetsWiredAndLabeled()

    Declaration
    public void Create_ValidInput_CreatesAllThreeAssetsWiredAndLabeled()

    OneTimeTearDown()

    The per-test deletion above goes through AssetDatabase.DeleteAsset, which stays consistent without a manual refresh between tests — flushing to disk once after the whole fixture is enough.

    Declaration
    public void OneTimeTearDown()

    ResolveProfileContext_ExistingProfileInFolder_ReturnsIt()

    Declaration
    public void ResolveProfileContext_ExistingProfileInFolder_ReturnsIt()

    ResolveProfileContext_NoMatchingProfileInFolder_ReturnsNullExistingAndNoAmbiguity()

    Declaration
    public void ResolveProfileContext_NoMatchingProfileInFolder_ReturnsNullExistingAndNoAmbiguity()

    SetUp()

    Declaration
    public void SetUp()

    TearDown()

    Declaration
    public void TearDown()

    TryMapDefaultLoggerKeyToChoice_KeyThisWizardDidNotAuthor_ReturnsFalse(string)

    Declaration
    public void TryMapDefaultLoggerKeyToChoice_KeyThisWizardDidNotAuthor_ReturnsFalse(string key)
    Parameters
    Type Name Description
    string key

    TryMapDefaultLoggerKeyToChoice_WizardAuthoredKey_MapsToItsChoice(string, DefaultLoggerChoice)

    Declaration
    public void TryMapDefaultLoggerKeyToChoice_WizardAuthoredKey_MapsToItsChoice(string key, LoggingProfileCreator.DefaultLoggerChoice expected)
    Parameters
    Type Name Description
    string key
    DefaultLoggerChoice expected

    Validate_BothSinksDisabled_ReturnsError()

    Declaration
    public void Validate_BothSinksDisabled_ReturnsError()

    Validate_CaseVariantProfileIdInSameFolder_IsRejectedBecauseAssetFileNamesCollide()

    Regression coverage: this creator had NO case-variant test at all, which is exactly why a blind global find-and-replace elsewhere silently flipped its in-folder lookup from OrdinalIgnoreCase to Ordinal with no rejection added — 'Profile_Orange' stopped resolving to the existing 'profile_orange' asset and instead created 'Profile_Orange.asset' right next to it, a file name Windows/macOS treats as identical to the one already there. Serenity Ids are case-sensitive, but a profile's Id also becomes its asset FILE NAME (NamingSanitizer.FileNameSafe), and file names are NOT case-sensitive on Windows/macOS — so Validate(Input) must reject this with an error (not merely warn), mirroring every sibling creator's Serenity.Global.Infrastructure.Editor.SerenityAssetIdRules.RejectCaseVariantInFolder``1(Serenity.Global.Infrastructure.Editor.SerenityAssetIdLookup.IdMatches{``0},System.String,System.String,System.String,Serenity.Global.Infrastructure.Editor.SerenityCreationValidationResult) call, and Create(Input) must refuse to run at all.

    Declaration
    public void Validate_CaseVariantProfileIdInSameFolder_IsRejectedBecauseAssetFileNamesCollide()

    Validate_DefaultLoggerPointsAtDisabledConsoleSink_ReturnsError()

    Declaration
    public void Validate_DefaultLoggerPointsAtDisabledConsoleSink_ReturnsError()

    Validate_DefaultLoggerPointsAtDisabledStructuredSink_ReturnsError()

    Declaration
    public void Validate_DefaultLoggerPointsAtDisabledStructuredSink_ReturnsError()

    Validate_DuplicateProfileIdElsewhereInProject_WarnsWithoutBlocking()

    The "elsewhere" folder here must NOT be nested under Serenity.Logging.Tests.Editor.Builder.LoggingProfileCreatorTests.TempFolder — UnityEditor.AssetDatabase.FindAssets(System.String,System.String[]) with a folder filter searches recursively, so a duplicate placed in a subfolder of the wizard's own output folder would be treated as the SAME resolvable existing profile (the by-Id-in-folder update path), not a project-wide duplicate. A sibling top-level folder is the only way to exercise the genuinely-elsewhere branch.

    Declaration
    public void Validate_DuplicateProfileIdElsewhereInProject_WarnsWithoutBlocking()

    Validate_EmptyProfileId_ReturnsError()

    Declaration
    public void Validate_EmptyProfileId_ReturnsError()

    Validate_FileSinkEnabledWithEmptyLogFileName_ReturnsError()

    Declaration
    public void Validate_FileSinkEnabledWithEmptyLogFileName_ReturnsError()

    Validate_LogFileNameContainsDotDot_ReturnsError()

    Declaration
    public void Validate_LogFileNameContainsDotDot_ReturnsError()

    Validate_LogFileNameContainsPathSeparator_ReturnsError()

    Declaration
    public void Validate_LogFileNameContainsPathSeparator_ReturnsError()

    Validate_MultipleConsoleSettingsAssetsExistInProject_WarnsAboutAmbiguityWithoutBlocking()

    Declaration
    public void Validate_MultipleConsoleSettingsAssetsExistInProject_WarnsAboutAmbiguityWithoutBlocking()

    Validate_NullInput_ReturnsMissingInputError()

    Declaration
    public void Validate_NullInput_ReturnsMissingInputError()

    Validate_OutputFolderOutsideAssets_ReturnsError()

    Declaration
    public void Validate_OutputFolderOutsideAssets_ReturnsError()

    Validate_StructuredSinkEnabledWithMaxRecordsLessThanOne_ReturnsError()

    Declaration
    public void Validate_StructuredSinkEnabledWithMaxRecordsLessThanOne_ReturnsError()
    In this article
    © 2026 Serenity. All Rights Reserved