Search Unity

Help Wanted Upgraded from latest 2018 to latest 2019. Now tests fail when loading scenes

Discussion in 'Testing & Automation' started by AcademyOfFetishes, Apr 30, 2019.

  1. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    When I run all my tests, I now get this error late in the run:

    Code (CSharp):
    1. Destroy may not be called from edit mode! Use DestroyImmediate instead.
    2. Also think twice if you really want to destroy something in edit mode. Since this will destroy objects permanently.
    3. 0x00007FF69BFB93CC (Unity) StackWalker::GetCurrentCallstack
    4. 0x00007FF69BFBC881 (Unity) StackWalker::ShowCallstack
    5. 0x00007FF69A728695 (Unity) GetStacktrace
    6. 0x00007FF69C9D6C60 (Unity) DebugStringToFile
    7. 0x00007FF69BF43634 (Unity) Scripting::DestroyObjectFromScripting
    8. 0x00007FF69C018FE3 (Unity) Object_CUSTOM_Destroy
    9. 0x0000022420BA8F96 (Mono JIT Code) (wrapper managed-to-native) UnityEngine.Object:Destroy (UnityEngine.Object,single)
    10. 0x0000022420BA8E6B (Mono JIT Code) [UnityEngineObject.bindings.cs:303] UnityEngine.Object:Destroy (UnityEngine.Object)
    11. 0x0000022420A3616B (Mono JIT Code) [Graphic.cs:511] UnityEngine.UI.Graphic:OnDestroy ()
    12. 0x0000022416212E18 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
    13. 0x00007FFE0399BBCB (mono-2.0-bdwgc) [mini-runtime.c:2809] mono_jit_runtime_invoke
    14. 0x00007FFE03922252 (mono-2.0-bdwgc) [object.c:2919] do_runtime_invoke
    15. 0x00007FFE0392B25F (mono-2.0-bdwgc) [object.c:2966] mono_runtime_invoke
    16. 0x00007FF69BF4B036 (Unity) scripting_method_invoke
    17. 0x00007FF69BF45335 (Unity) ScriptingInvocation::Invoke
    18. 0x00007FF69BF455DE (Unity) ScriptingInvocation::InvokeChecked
    19. 0x00007FF69BF9FAF3 (Unity) SerializableManagedRef::CallMethod
    20. 0x00007FF69BF19966 (Unity) MonoBehaviour::WillDestroyComponent
    21. 0x00007FF69B21F1EE (Unity) GameObject::WillDestroyGameObject
    22. 0x00007FF69BA31C25 (Unity) PreDestroyRecursive
    23. 0x00007FF69BA31CE6 (Unity) PreDestroyRecursive
    24. 0x00007FF69BA31CE6 (Unity) PreDestroyRecursive
    25. 0x00007FF69BA31CE6 (Unity) PreDestroyRecursive
    26. 0x00007FF69BA31CE6 (Unity) PreDestroyRecursive
    27. 0x00007FF69BA31CE6 (Unity) PreDestroyRecursive
    28. 0x00007FF69BA31CE6 (Unity) PreDestroyRecursive
    29. 0x00007FF69BA31CE6 (Unity) PreDestroyRecursive
    30. 0x00007FF69BA31CE6 (Unity) PreDestroyRecursive
    31. 0x00007FF69BA2F3FB (Unity) DestroyObjectHighLevel_Internal
    32. 0x00007FF69BA2F21E (Unity) DestroyObjectHighLevel
    33. 0x00007FF69BA43485 (Unity) DestroyWorldObjects
    34. 0x00007FF69A20BD04 (Unity) EditorSceneManager::RestoreSceneBackups
    35. 0x00007FF69A20B558 (Unity) EditorSceneManager::OpenSceneLoaded
    36. 0x00007FF69A20A574 (Unity) EditorSceneManager::OpenScene
    37. 0x00007FF69A455213 (Unity) EditorSceneManagerBindings::OpenScene
    38. 0x00007FF69AF735FF (Unity) EditorSceneManager_CUSTOM_OpenScene_Injected
    39. 0x0000022420A2EC00 (Mono JIT Code) (wrapper managed-to-native) UnityEditor.SceneManagement.EditorSceneManager:OpenScene_Injected (string,UnityEditor.SceneManagement.OpenSceneMode,UnityEngine.SceneManagement.Scene&)
    40. 0x0000022420A2EA9B (Mono JIT Code) UnityEditor.SceneManagement.EditorSceneManager:OpenScene (string,UnityEditor.SceneManagement.OpenSceneMode)
    41. 0x0000022420A2E943 (Mono JIT Code) [EditorSceneManager.cs:32] UnityEditor.SceneManagement.EditorSceneManager:OpenScene (string)
    42. 0x0000022420A2E523 (Mono JIT Code) [TestSceneLoader.cs:10] TestSceneLoader:ReloadLevelScene ()
    43. 0x0000022420A6B0BB (Mono JIT Code) [LevelAcceptanceTests.cs:38] LevelAcceptanceTests:SetUp ()
    44. 0x000002242074AEF0 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
    45. 0x00007FFE0399BBCB (mono-2.0-bdwgc) [mini-runtime.c:2809] mono_jit_runtime_invoke
    46. 0x00007FFE03922252 (mono-2.0-bdwgc) [object.c:2919] do_runtime_invoke
    47. 0x00007FFE0392B432 (mono-2.0-bdwgc) [object.c:3071] mono_runtime_invoke_checked
    48. 0x00007FFE0392BBC9 (mono-2.0-bdwgc) [object.c:5262] mono_runtime_try_invoke_array
    49. 0x00007FFE0392B3C6 (mono-2.0-bdwgc) [object.c:5140] mono_runtime_invoke_array_checked
    50. 0x00007FFE038D0254 (mono-2.0-bdwgc) [icall.c:3358] ves_icall_InternalInvoke
    51. 0x0000022412DA0436 (Mono JIT Code) (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
    52. 0x0000022412D9FBBB (Mono JIT Code) System.Reflection.MonoMethod:Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo)
    53. 0x00000224144D183F (Mono JIT Code) System.Reflection.MethodBase:Invoke (object,object[])
    54. 0x000002242074D793 (Mono JIT Code) NUnit.Framework.Internal.Reflect:InvokeMethod (System.Reflection.MethodInfo,object,object[])
    55. 0x000002242074D2A3 (Mono JIT Code) NUnit.Framework.Internal.Reflect:InvokeMethod (System.Reflection.MethodInfo,object)
    56. 0x000002242074D14B (Mono JIT Code) NUnit.Framework.Internal.Commands.SetUpTearDownItem:RunNonAsyncMethod (System.Reflection.MethodInfo,NUnit.Framework.Internal.ITestExecutionContext)
    57. 0x000002242074CFB3 (Mono JIT Code) NUnit.Framework.Internal.Commands.SetUpTearDownItem:RunSetUpOrTearDownMethod (NUnit.Framework.Internal.ITestExecutionContext,System.Reflection.MethodInfo)
    58. 0x000002242074CB33 (Mono JIT Code) NUnit.Framework.Internal.Commands.SetUpTearDownItem:RunSetUp (NUnit.Framework.Internal.ITestExecutionContext)
    59. 0x0000022420757D8B (Mono JIT Code) [SetUpTearDownCommand.cs:25] UnityEngine.TestTools.SetUpTearDownCommand/<InvokeBefore>c__Iterator0:MoveNext ()
    60. 0x0000022420754B6E (Mono JIT Code) [BeforeAfterTestCommandBase.cs:57] UnityEngine.TestTools.BeforeAfterTestCommandBase`1/<ExecuteEnumerable>c__Iterator0<T_REF>:MoveNext ()
    61. 0x0000022420755C8A (Mono JIT Code) [BeforeAfterTestCommandBase.cs:99] UnityEngine.TestTools.BeforeAfterTestCommandBase`1/<ExecuteEnumerable>c__Iterator0<T_REF>:MoveNext ()
    62. 0x0000022420755C8A (Mono JIT Code) [BeforeAfterTestCommandBase.cs:99] UnityEngine.TestTools.BeforeAfterTestCommandBase`1/<ExecuteEnumerable>c__Iterator0<T_REF>:MoveNext ()
    63. 0x0000022420A69BDA (Mono JIT Code) [EditorEnumeratorTestWorkItem.cs:101] UnityEditor.TestTools.TestRunner.EditorEnumeratorTestWorkItem/<PerformWork>c__Iterator0:MoveNext ()
    64. 0x0000022420744559 (Mono JIT Code) [CompositeWorkItem.cs:200] UnityEngine.TestRunner.NUnitExtensions.Runner.CompositeWorkItem/<RunChildren>c__Iterator1:MoveNext ()
    65. 0x000002242073BAC9 (Mono JIT Code) [CompositeWorkItem.cs:76] UnityEngine.TestRunner.NUnitExtensions.Runner.CompositeWorkItem/<PerformWork>c__Iterator0:MoveNext ()
    66. 0x0000022420744559 (Mono JIT Code) [CompositeWorkItem.cs:200] UnityEngine.TestRunner.NUnitExtensions.Runner.CompositeWorkItem/<RunChildren>c__Iterator1:MoveNext ()
    67. 0x000002242073BAC9 (Mono JIT Code) [CompositeWorkItem.cs:76] UnityEngine.TestRunner.NUnitExtensions.Runner.CompositeWorkItem/<PerformWork>c__Iterator0:MoveNext ()
    68. 0x0000022420744559 (Mono JIT Code) [CompositeWorkItem.cs:200] UnityEngine.TestRunner.NUnitExtensions.Runner.CompositeWorkItem/<RunChildren>c__Iterator1:MoveNext ()
    69. 0x000002242073BAC9 (Mono JIT Code) [CompositeWorkItem.cs:76] UnityEngine.TestRunner.NUnitExtensions.Runner.CompositeWorkItem/<PerformWork>c__Iterator0:MoveNext ()
    70. 0x0000022420744559 (Mono JIT Code) [CompositeWorkItem.cs:200] UnityEngine.TestRunner.NUnitExtensions.Runner.CompositeWorkItem/<RunChildren>c__Iterator1:MoveNext ()
    71. 0x000002242073BAC9 (Mono JIT Code) [CompositeWorkItem.cs:76] UnityEngine.TestRunner.NUnitExtensions.Runner.CompositeWorkItem/<PerformWork>c__Iterator0:MoveNext ()
    72. 0x000002242073A4AE (Mono JIT Code) [EditModeRunner.cs:219] UnityEditor.TestTools.TestRunner.EditModeRunner:MoveNextAndUpdateYieldObject ()
    73. 0x000002242073A07B (Mono JIT Code) [EditModeRunner.cs:252] UnityEditor.TestTools.TestRunner.EditModeRunner:TestConsumer ()
    74. 0x0000022425960D07 (Mono JIT Code) (wrapper delegate-invoke) <Module>:invoke_void ()
    75. 0x0000022425960A07 (Mono JIT Code) [EditorApplication.cs:200] UnityEditor.EditorApplication:Internal_CallUpdateFunctions ()
    76. 0x000002241444D3F5 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr)
    77. 0x00007FFE0399BBCB (mono-2.0-bdwgc) [mini-runtime.c:2809] mono_jit_runtime_invoke
    78. 0x00007FFE03922252 (mono-2.0-bdwgc) [object.c:2919] do_runtime_invoke
    79. 0x00007FFE0392B25F (mono-2.0-bdwgc) [object.c:2966] mono_runtime_invoke
    80. 0x00007FF69BF42A31 (Unity) CallStaticMonoMethod
    81. 0x00007FF69BF42631 (Unity) CallStaticMonoMethod
    82. 0x00007FF69BF423B1 (Unity) CallStaticMonoMethod
    83. 0x00007FF69A4C74F6 (Unity) SceneTracker::Update
    84. 0x00007FF69A77399B (Unity) Application::TickTimer
    85. 0x00007FF69AA33943 (Unity) MainMessageLoop
    86. 0x00007FF69AA3D347 (Unity) WinMain
    87. 0x00007FF69D36DD8E (Unity) __scrt_common_main_seh
    88. 0x00007FFE416F4034 (KERNEL32) BaseThreadInitThunk
    89. 0x00007FFE42493691 (ntdll) RtlUserThreadStart
    90.  
    91.  
    If I run a test that failed like this all by itself, it then passes.

    You're probably interested in this code:

    Code (CSharp):
    1. 0x0000022420A2E523 (Mono JIT Code) [TestSceneLoader.cs:10] TestSceneLoader:ReloadLevelScene ()
    2. 0x0000022420A6B0BB (Mono JIT Code) [LevelAcceptanceTests.cs:38] LevelAcceptanceTests:SetUp ()
    3.  
    Here's what the TestSceneLoader is doing on that line:

    Code (CSharp):
    1.     public static void ReloadLevelScene()
    2.     {
    3.         var scene = EditorSceneManager.GetSceneByPath("Assets/Scenes/Level.unity");
    4.         EditorSceneManager.OpenScene("Assets/Scenes/Level.unity");
    5.     }
    It's important to note that these are Edit Mode tests. That Setup is run like 10+ times before this error happens. It always seems to happen on the same tests too, but if I run any of them individually, the tests pass.

    Here's my guess: Unity is now better at cleaning up after itself. Now, it's running Destroy on objects that I left behind, but it's calling the wrong destroy, so I get this error.

    Anyway, any help would be appreciated. I'm going to delete my Library directory to see if it fixes this, because it seems to always solve half the bugs I run into with Unity.
     
    Last edited: Apr 30, 2019
  2. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    OK, I've done a little more research, and discovered that if a test has this
    TestUtils.CallInitialization(GameObject.Find("StatsRenderer"));
    in it, the NEXT test will fail with the error above. If I comment out that line, this does not happen.

    That line is calling Awake, OnEnable, and Start respectively on my StatsRenderer. It's using reflection to do so.

    Here's how my StatsRenderer looks:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Serialization;
    5. using UnityEngine.UI;
    6. using CollectionUtils;
    7. using TMPro;
    8.  
    9. public class StatsRenderer : MonoBehaviour
    10. {
    11.     public LevelData levelData;
    12.     public Transform informationPanel;
    13.     public GameObject needsFulfilledTextTemplate;
    14.     public GameObject levelRewardsGameObject;
    15.     private LevelRewardCalculator levelRewardCalculator;
    16.     private Dictionary<string, CharacterData> rewardNameToData = new Dictionary<string, CharacterData>();
    17.     void Start()
    18.     {
    19.         foreach (var characterData in ScriptableObjectLoader.LoadAllCharacterData())
    20.         {
    21.             rewardNameToData.Add(characterData.skillPointName, characterData);
    22.         }
    23.  
    24.         levelRewardCalculator = new LevelRewardCalculator();
    25.         foreach (var characterStat in levelData.GetCharacterStats())
    26.         {
    27.             GameObject textGameObject = Instantiate(needsFulfilledTextTemplate, informationPanel);
    28.             textGameObject.name = characterStat.characterName + "NeedsFulfilledText";
    29.        
    30.             textGameObject.GetComponent<TextMeshProUGUI>().text = $"{characterStat.characterName}'s Needs Fulfilled: {characterStat.successfulCount}/{characterStat.totalCount}";
    31.         }
    32.  
    33.         foreach (var characterStat in levelData.GetCharacterStats())
    34.         {
    35.             if (characterStat.levelsGained > 0)
    36.             {
    37.                 GameObject textGameObject = Instantiate(needsFulfilledTextTemplate, informationPanel);
    38.                 textGameObject.name = characterStat.characterName + "LevelUpText";
    39.  
    40.                 string level = characterStat.levelsGained > 1 ? $"{characterStat.levelsGained} levels" : "a level";
    41.                 textGameObject.GetComponent<TextMeshProUGUI>().text = $"{characterStat.characterName} gained {level}!";
    42.  
    43.             }
    44.         }
    45.         Dictionary<string, int> levelRewards = levelRewardCalculator.CalculateLevelRewards(levelData, Repository.instance.repositoryData.gameStats);
    46.         foreach (var entry in levelRewards)
    47.         {
    48.             if (entry.Value > 0 && entry.Key != "Money")
    49.             {
    50.                 AddReward(entry.Key, entry.Value);
    51.             }
    52.         }
    53.         if (levelRewards["Money"] > 0)
    54.         {
    55.             GameObject rewardGameObjectTemplate = Resources.Load<GameObject>("MoneyReward");
    56.             var rewardGameObject = Instantiate(rewardGameObjectTemplate, levelRewardsGameObject.transform);
    57.             rewardGameObject.name = "MoneyReward";
    58.             rewardGameObject.transform.Find("Text").GetComponent<TextMeshProUGUI>().text = "+" + levelRewards["Money"] + " Money";
    59.         }
    60.         levelRewardsGameObject.transform.SetAsLastSibling();
    61.     }
    62.  
    63.     private void AddReward(string rewardName, int rewardValue)
    64.     {
    65.         GameObject rewardGameObjectTemplate = Resources.Load<GameObject>("SkillPointReward");
    66.         if (rewardGameObjectTemplate == null)
    67.         {
    68.             throw new System.NullReferenceException("Could not load a prefab named " + "SkillPointReward");
    69.         }
    70.         var rewardGameObject = Instantiate(rewardGameObjectTemplate, levelRewardsGameObject.transform);
    71.         rewardGameObject.name = rewardName + "Reward";
    72.         rewardGameObject.transform.Find("Text").GetComponent<TextMeshProUGUI>().text = "+" + rewardValue + " " + rewardName;
    73.         try
    74.         {
    75.             rewardGameObject.transform.Find("Background").Find("Image").GetComponent<Image>().sprite = rewardNameToData[rewardName].skillPointImage;
    76.             rewardGameObject.transform.Find("Background").Find("Image").GetComponent<Image>().color = rewardNameToData[rewardName].skillPointTint;
    77.         }
    78.         catch (KeyNotFoundException e)
    79.         {
    80.             throw new KeyNotFoundException($"Was looking for {rewardName} in {rewardNameToData.PrettyToString()}", e);
    81.         }
    82.     }
    83.  
    84. }
    85.  
    Still looking into this. I have a feeling I can find the exact line causing the problem by commenting out parts of this.

    The error only happens if I call
    AddReward(entry.Key, entry.Value);


    OK, I have no idea why, but for whatever reason, this single line is the cause of the problems:

    Code (CSharp):
    1. rewardGameObject.transform.Find("Background").Find("Image").GetComponent<Image>().sprite = rewardNameToData[rewardName].skillPointImage;
    The very similar line the occurs after it is not:

    Code (CSharp):
    1. rewardGameObject.transform.Find("Background").Find("Image").GetComponent<Image>().color = rewardNameToData[rewardName].skillPointTint;
    It's not obvious to me why in 2018, the first line would be fine and in 2019 it causes an error when you try to reload the scene. Anyone else know?

    If I do this line instead, the error does not happen:

    Code (CSharp):
    1. rewardGameObject.transform.Find("Background").Find("Image").GetComponent<Image>().sprite = null;
     
    Last edited: Apr 30, 2019
  3. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    OK i've confirmed this happens from the scene closing, not from my code. Something in Unity is trying to destroy my object using Destroy instead of DestroyImmediate. I think there's a chance this could be a Unity bug because it seems like Unity doesn't understand it's in edit mode, and is trying to use Destroy to clean up instead of DestroyImmediate.
     
  4. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,235
    did u try using different unity versions to see if it gives different results?
    also, are you running it on a local machine, or on some sort of build server ?
     
  5. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    Can you give an example? It already works fine on the latest 2018. There's only one 2019, so I think I've tried it on everything possible.
    Local.
     
  6. BazookasZerreth

    BazookasZerreth

    Joined:
    Dec 8, 2016
    Posts:
    17
    I'm experiencing the same error ("Destroy may not be called from edit mode! Use DestroyImmediate instead.") when messing with sprites in editor.
     
  7. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,265
    I get this error from one of my code-generated Canvas/Image/Sprite object that's with
    HideFlags.DontSave
    on it. When the test wants to destroy this object it cause the error. (case : https://fogbugz.unity3d.com/default.asp?1157422_sfvtcfi1jmvc3702)