Ruby 3 support related to mocha gem

I have another topic to support Ruby 3.

Steps to reproduce

$ bundle exec rspec ./spec/lib/backup_restore/database_restorer_multisite_spec.rb:15

Actual result with Ruby 3.0.2

$ ruby -v
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]
$ bundle exec rspec ./spec/lib/backup_restore/database_restorer_multisite_spec.rb:15
Run options: include {:locations=>{"./spec/lib/backup_restore/database_restorer_multisite_spec.rb"=>[15]}}

Randomized with seed 43732
F

Failures:

  1) BackupRestore::DatabaseRestorer#restore database connection reconnects to the correct database
     Failure/Error:
       log Discourse::Utils.execute_command(
         {
           "SKIP_POST_DEPLOYMENT_MIGRATIONS" => "0",
           "SKIP_OPTIMIZE_ICONS" => "1",
           "DISABLE_TRANSLATION_OVERRIDES" => "1"
         },
         "rake", "db:migrate",
         failure_message: "Failed to migrate database.",
         chdir: Rails.root
       )

     Mocha::ExpectationError:
       unexpected invocation: Discourse::Utils.execute_command({"SKIP_POST_DEPLOYMENT_MIGRATIONS" => "0", "SKIP_OPTIMIZE_ICONS" => "1", "DISABLE_TRANSLATION_OVERRIDES" => "1"}, "rake", "db:migrate", {:failure_message => "Failed to migrate database.", :chdir => #<Pathname:0xd548>})
       unsatisfied expectations:
       - expected exactly once, invoked never: Discourse::Utils.execute_command()
       satisfied expectations:
       - expected exactly once, invoked once: BackupRestore.move_tables_between_schemas("public", "backup")
       - expected at least once, invoked 77 times: Migration::BaseDropper.create_readonly_function(any_parameters)
       - expected exactly once, invoked once: #<Mock:psql status>.exitstatus(any_parameters)
       - expected exactly once, invoked once: Process.last_status(any_parameters)
       - expected exactly twice, invoked twice: #<Mock:psql>.readline(any_parameters)
       - expected exactly once, invoked once: IO.popen(any_parameters)
     # ./lib/backup_restore/database_restorer.rb:138:in `migrate_database'
     # ./lib/backup_restore/database_restorer.rb:27:in `restore'
     # ./spec/lib/backup_restore/shared_context_for_backup_restore.rb:59:in `execute_stubbed_restore'
     # ./spec/lib/backup_restore/database_restorer_multisite_spec.rb:17:in `block (4 levels) in <top (required)>'
     # ./spec/rails_helper.rb:279:in `block (2 levels) in <top (required)>'

Finished in 0.28437 seconds (files took 2.37 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/lib/backup_restore/database_restorer_multisite_spec.rb:15 # BackupRestore::DatabaseRestorer#restore database connection reconnects to the correct database

Randomized with seed 43732

$

Actual result with Ruby 2.7.4

$ ruby -v
ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x86_64-linux]
$ bundle exec rspec ./spec/lib/backup_restore/database_restorer_multisite_spec.rb:15
Run options: include {:locations=>{"./spec/lib/backup_restore/database_restorer_multisite_spec.rb"=>[15]}}

Randomized with seed 37771
.

Finished in 0.63589 seconds (files took 2.63 seconds to load)
1 example, 0 failures

Randomized with seed 37771

$

What I’ve found so far

Actually, this is another Ruby 3 keyword arguments support required.

  • Execute with Ruby 2.7.4 enabling -w and find warning: Using the last argument as keyword parameters is deprecated
$ bundle exec rspec -w ./spec/lib/backup_restore/database_restorer_multisite_spec.rb:15 2>&1 | grep keyword
/home/yahonda/.rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/mocha-1.13.0/lib/mocha/parameters_matcher.rb:13: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
  • Here is the quick dirty fix with print debug code.
$ git diff 191823e8696881ab8c72948165834eca18315cb3...8141f2f0eca4bedcf59e34f31dd9ca35e39c2a25
diff --git a/lib/mocha/parameters_matcher.rb b/lib/mocha/parameters_matcher.rb
index 2b6ed84..26c4a25 100644
--- a/lib/mocha/parameters_matcher.rb
+++ b/lib/mocha/parameters_matcher.rb
@@ -10,7 +10,11 @@ module Mocha

     def match?(actual_parameters = [])
       if @matching_block
-        @matching_block.call(*actual_parameters)
+        p actual_parameters
+        if actual_parameters.last.is_a? Hash
+          kwargs = actual_parameters.pop
+        end
+        @matching_block.call(*actual_parameters, **kwargs)
       else
         parameters_match?(actual_parameters)
       end
$

Result with modified mocha code

$ bundle exec rspec ./spec/lib/backup_restore/database_restorer_multisite_spec.rb:15
Run options: include {:locations=>{"./spec/lib/backup_restore/database_restorer_multisite_spec.rb"=>[15]}}

Randomized with seed 27573
[{"SKIP_POST_DEPLOYMENT_MIGRATIONS"=>"0", "SKIP_OPTIMIZE_ICONS"=>"1", "DISABLE_TRANSLATION_OVERRIDES"=>"1"}, "rake", "db:migrate", {:failure_message=>"Failed to migrate database.", :chdir=>#<Pathname:/home/yahonda/src/github.com/discourse/discourse>}]
.

Finished in 0.40263 seconds (files took 2.88 seconds to load)
1 example, 0 failures

Randomized with seed 27573

$

I may need to create a minimum case for mocha. It would be appreciated if someone has suggestions.

2 Likes

Yes looks like a fix for mocha, did you end up opening a bug report for this in GitHub?

Not yet. I’ll take some more look at it this week.

1 Like

I’ve found a similar issue reported and a workaround is explained

use kwargs vs **kwargs, then kwargs will be a Hash which you can use in your assertion and no warnings will be generated…

Applying the workaround suggested makes failing specs green.

https://github.com/yahonda/discourse/commit/356f15b02cb4a0bb869d19adf2a2018d07ee79bf

$ git diff main
diff --git a/spec/lib/backup_restore/shared_context_for_backup_restore.rb b/spec/lib/backup_restore/shared_context_for_backup_restore.rb
index 2ff78176ea..0fbc8ade15 100644
--- a/spec/lib/backup_restore/shared_context_for_backup_restore.rb
+++ b/spec/lib/backup_restore/shared_context_for_backup_restore.rb
@@ -33,7 +33,7 @@ shared_context "shared stuff" do
   end

   def expect_db_migrate
-    Discourse::Utils.expects(:execute_command).with do |env, *command, **options|
+    Discourse::Utils.expects(:execute_command).with do |env, *command, options|
       env["SKIP_POST_DEPLOYMENT_MIGRATIONS"] == "0" &&
         env["SKIP_OPTIMIZE_ICONS"] == "1" &&
         env["DISABLE_TRANSLATION_OVERRIDES"] == "1" &&
$

I am happy to open a pull request.

2 Likes

Opened FIX: `BackupRestore::DatabaseRestorer` failures with Ruby 3 by yahonda · Pull Request #14580 · discourse/discourse · GitHub

1 Like