zachallaun/mneme

Mneme fails to find the assertion AST node when performing an update

Closed this issue · 14 comments

     test/domain_modelling/exercise_events_test.exs:311
     ** (Mneme.InternalError) Mneme encountered an internal error. This is likely a bug in Mneme.

     Please consider reporting this error at https://github.com/zachallaun/mneme/issues. Thanks!

     ** (FunctionClauseError) no function clause matching in Sourceror.Zipper.node/1
         (sourceror 0.14.0) lib/sourceror/zipper.ex:100: Sourceror.Zipper.node(nil)
         (mneme 0.4.1) lib/mneme/patcher.ex:116: Mneme.Patcher.prepare_assertion/2
         (mneme 0.4.1) lib/mneme/patcher.ex:53: Mneme.Patcher.patch!/3
         (mneme 0.4.1) lib/mneme/server.ex:171: Mneme.Server.do_patch_assertion/2
         (mneme 0.4.1) lib/mneme/server.ex:163: Mneme.Server.handle_continue/2
         (stdlib 4.3.1.2) gen_server.erl:1123: :gen_server.try_dispatch/4
         (stdlib 4.3.1.2) gen_server.erl:865: :gen_server.loop/7
         (stdlib 4.3.1.2) proc_lib.erl:240: :proc_lib.init_p_do_apply/3


     code: auto_assert [
     stacktrace:
       (mneme 0.4.1) lib/mneme/assertion.ex:161: Mneme.Assertion.handle_assertion/4
       (mneme 0.4.1) lib/mneme/assertion.ex:121: Mneme.Assertion.do_run/3
       (mneme 0.4.1) lib/mneme/assertion.ex:102: Mneme.Assertion.run/3
       test/domain_modelling/exercise_events_test.exs:321: (test)

trying to create a reproduction. Unsuccessful so far.

This happens when, for some reason, Mneme isn't able to find the node that it needs to replace in the AST for an update.

I have a hunch that it may be a race condition relating to the file changing while, for instance, Mneme is paused waiting for a prompt in another file. I'll test this theory a bit later and will fix if that's the case, but I'll minimally catch this exception and print a better error with some extra debugging information for later!

That could be it. The weird thing though is that it happened at least 2 times today while I've never had this in the past?
Either a coincidence or something has changed that triggers this more often?

Hmm... Could definitely be something that changed between v0.4.0 and v0.4.1. There was a lot of code touched, but very few (I thought) behavioral changes -- I started using elixir-styler.

Would you be able to share the test that the error occurred during? This one:

test/domain_modelling/exercise_events_test.exs:321

The good news is that I was just able to recreate it while doing this:

I have a hunch that it may be a race condition relating to the file changing while, for instance, Mneme is paused waiting for a prompt in another file.

I'll work on a fix.

Should be fixed in v0.4.2. Note that the test run will still fail in these cases -- Mneme needs to be really conservative when the test file changes and just bail out -- but it'll now skip those tests and show a nice error at the end that looks like this:

[Mneme] The following files could not be saved. Their content may have changed.

  * /home/z/dev/mneme/test/mneme/diff_test.exs

You may need to run these tests again.

@zachallaun something definitely changed in the latest version. I've got this error again, but as far as I know, I didn't change the file, but mneme did change it by accepting a suggestion.
Again, haven't been able to reproduce it every time, but I've seen this happening now a few times, and it was always after I accepted a suggestion by mneme.

I've used both linux and mac

@tcoopman Just to confirm -- You're still seeing the error on 0.4.2? Or you're seeing the new error message, but it still seems like something new that's happened since 0.4.0 is causing it to trigger a lot more frequently?

It looks like something that's happening more frequently since 0.4.0
But I'm not sure. I've tried to reproduce with a custom test file, but haven't been able to trigger it...

I have a reproduction. Notice the bad formatting:

    test "1" do
      events = 
{:ok,
 [
   %DomainModelling.Event{
     payload: %DomainModelling.ExerciseEventsTest.QuestionAnsweredCorrectly{
       id: "1",
       answer: "answer",
       block_id: %DomainModelling.BlockId{block: 1, page: 0}
     },
     type: "QuestionAnsweredCorrectly",
     created_at: ~U[2023-11-01 19:46:32.254112Z],
     event_id: "018b8c6c-56be-7b5b-b088-ef15c487b0ac"
   }
 ]}
      auto_assert events
    end

    test "2" do
      events = 
{:ok,
 [
   %DomainModelling.Event{
     payload: %DomainModelling.ExerciseEventsTest.QuestionAnsweredCorrectly{
       id: "1",
       answer: "answer",
       block_id: %DomainModelling.BlockId{block: 1, page: 0}
     },
     type: "QuestionAnsweredCorrectly",
     created_at: ~U[2023-11-01 19:46:32.254112Z],
     event_id: "018b8c6c-56be-7b5b-b088-ef15c487b0ac"
   }
 ]}
      auto_assert {:ok,
                   [
                     %Event{
                       payload: %QuestionAnsweredCorrectly{
                         block_id: 
      
      
      %BlockId{page: 0, block: 5},
                       }
                     }
                   ]} <- events
    end

When test "1" is evaluated first, you press j, then y, then it always fails for me

@tcoopman Thank you so much for the reproduction. That make it very easy to track down (and hopefully fix) the issue. Before I cut a new release, would you mind trying out this latest commit on main and making sure that things are now working as you expect? i.e. you can have unformatted code/assertions, and Mneme will still go through them all and format everything at the end.

@zachallaun I can confirm that main fixes the bug. I'll use it for now :)
Thanks for the quick fix!!

Thank you for double-checking!

I'm going to look into the aliases thing and see if I can get a fix in for that before cutting a new release.

cool, I hope you find something for the aliases, but having read into it a bit, I think it might not be easy (hopefully I'm wrong)